home *** CD-ROM | disk | FTP | other *** search
- /* Window creation, deletion and examination for XEmacs.
- Copyright (C) 1985-1987, 1992-1995 Free Software Foundation, Inc.
- Copyright (C) 1994, 1995 Board of Trustees, University of Illinois
-
- This file is part of XEmacs.
-
- XEmacs is free software; you can redistribute it and/or modify it
- under the terms of the GNU General Public License as published by the
- Free Software Foundation; either version 2, or (at your option) any
- later version.
-
- XEmacs is distributed in the hope that it will be useful, but WITHOUT
- ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- for more details.
-
- You should have received a copy of the GNU General Public License
- along with XEmacs; see the file COPYING. If not, write to the Free
- Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
-
- /* Synched up with: FSF 19.28, except for `display-buffer'. */
- /* Beginning to diverge significantly. */
-
- /* This file has been Mule-ized. */
-
- #include <config.h>
- #include "lisp.h"
-
- #include "buffer.h"
- #include "device.h"
- #include "faces.h"
- #include "frame.h"
- #include "glyphs.h"
- #include "redisplay.h"
- #include "window.h"
- #include "commands.h"
-
- Lisp_Object Qwindowp, Qwindow_live_p;
- Lisp_Object Qwindow_configurationp;
- Lisp_Object Qscroll_up;
- Lisp_Object Qscroll_down;
- Lisp_Object Qvisible;
-
- static int window_pixel_width_to_char_width (struct window *w,
- int pixel_width,
- int include_margins_p);
- static int window_char_width_to_pixel_width (struct window *w,
- int char_width,
- int include_margins_p);
- static int window_pixel_height_to_char_height (struct window *w,
- int pixel_height,
- int include_modeline_p);
- static int window_char_height_to_pixel_height (struct window *w,
- int char_height,
- int include_modeline_p);
-
- #ifdef ENERGIZE
- extern void energize_buffer_shown_hook ();
- extern void energize_buffer_hidden_hook ();
- extern void energize_window_selected_hook ();
- extern void energize_window_deselected_hook ();
- extern Lisp_Object desired_psheet_buffer ();
- extern void make_psheets_desired ();
- #endif
-
- /* Thickness of shadow border around 3d modelines. */
- Lisp_Object Vmodeline_shadow_thickness;
-
- /* Whether a modeline should be displayed. */
- Lisp_Object Vhas_modeline_p;
-
- /* Scroll if point lands on the bottom line and that line is partially
- clipped. */
- int scroll_on_clipped_lines;
-
- /* The minibuffer window of the selected frame.
- Note that you cannot test for minibufferness of an arbitrary window
- by comparing against this; but you can test for minibufferness of
- the selected window. */
- Lisp_Object minibuf_window;
-
- /* Non-nil means it is the window for C-M-v to scroll
- when the minibuffer is selected. */
- Lisp_Object Vminibuf_scroll_window;
-
- /* Non-nil means this is the buffer whose window C-M-v should scroll. */
- Lisp_Object Vother_window_scroll_buffer;
-
- /* Non-nil means it's function to call to display temp buffers. */
- Lisp_Object Vtemp_buffer_show_function;
-
- /* If a window gets smaller than either of these, it is removed. */
- int window_min_height;
- int window_min_width;
-
- /* Nonzero implies Fdisplay_buffer should create windows. */
- int pop_up_windows;
-
- #if 0 /* FSFmacs */
- /* Nonzero implies make new frames for Fdisplay_buffer. */
- int pop_up_frames;
-
- /* Non-nil means use this function instead of default */
- Lisp_Object Vpop_up_frame_function;
- #endif
-
- /* Function to call *instead of* Fdisplay_buffer. */
- Lisp_Object Vdisplay_buffer_function;
-
- /* Function to call as the first thing that Fdisplay_buffer does (can be
- used to select an appropriate frame, for example). */
- Lisp_Object Vpre_display_buffer_function;
-
- #if 0 /* FSFmacs */
- /* List of buffer *names* for buffers that should have their own frames. */
- Lisp_Object Vspecial_display_buffer_names;
-
- /* List of regexps for buffer names that should have their own frames. */
- Lisp_Object Vspecial_display_regexps;
-
- /* Function to pop up a special frame. */
- Lisp_Object Vspecial_display_function;
- #endif
-
- /* Fdisplay_buffer always splits the largest window
- if that window is more than this high. */
- int split_height_threshold;
-
- /* Fdisplay_buffer always splits the largest window
- if that window is more than this wide. */
- int split_width_threshold;
-
- /* Number of lines of continuity in scrolling by screenfuls. */
- int next_screen_context_lines;
-
- #define SET_LAST_MODIFIED(w, cache_too) \
- do { \
- (w)->last_modified[CURRENT_DISP] = Qzero; \
- (w)->last_modified[DESIRED_DISP] = Qzero; \
- (w)->last_modified[CMOTION_DISP] = Qzero; \
- if (cache_too) \
- (w)->line_cache_last_updated = Qzero; \
- } while (0)
-
- #define SET_LAST_FACECHANGE(w) \
- do { \
- (w)->last_facechange[CURRENT_DISP] = Qzero; \
- (w)->last_facechange[DESIRED_DISP] = Qzero; \
- (w)->last_facechange[CMOTION_DISP] = Qzero; \
- } while (0)
-
-
- DEFUN ("windowp", Fwindowp, Swindowp, 1, 1, 0,
- "Return t if OBJ is a window.")
- (obj)
- Lisp_Object obj;
- {
- return (WINDOWP (obj) ? Qt : Qnil);
- }
-
- DEFUN ("window-live-p", Fwindow_live_p, Swindow_live_p, 1, 1, 0,
- "Return t if OBJ is a window which is currently visible.")
- (obj)
- Lisp_Object obj;
- {
- return (WINDOWP (obj) && WINDOW_LIVE_P (XWINDOW (obj)) ? Qt : Qnil);
- }
-
- static Lisp_Object mark_window (Lisp_Object, void (*) (Lisp_Object));
- static void print_window (Lisp_Object, Lisp_Object, int);
- static void finalize_window (void *header, int for_disksave);
- DEFINE_LRECORD_IMPLEMENTATION ("window", window,
- mark_window, print_window, finalize_window,
- 0, 0, struct window);
-
- #define MARK_DISP_VARIABLE(field) \
- ((markobj) (window->field[CURRENT_DISP])); \
- ((markobj) (window->field[DESIRED_DISP])); \
- ((markobj) (window->field[CMOTION_DISP]));
-
- static Lisp_Object
- mark_window (Lisp_Object obj, void (*markobj) (Lisp_Object))
- {
- struct window *window = XWINDOW (obj);
- ((markobj) (window->frame));
- ((markobj) (window->mini_p));
- ((markobj) (window->next));
- ((markobj) (window->prev));
- ((markobj) (window->hchild));
- ((markobj) (window->vchild));
- ((markobj) (window->parent));
- ((markobj) (window->buffer));
- MARK_DISP_VARIABLE (start);
- MARK_DISP_VARIABLE (pointm);
- ((markobj) (window->sb_point)); /* #### move to scrollbar.c? */
- ((markobj) (window->use_time));
- MARK_DISP_VARIABLE (last_modified);
- MARK_DISP_VARIABLE (last_point);
- MARK_DISP_VARIABLE (last_start);
- MARK_DISP_VARIABLE (last_facechange);
- ((markobj) (window->line_cache_last_updated));
- /* Cached specifiers: */
- ((markobj) (window->display_table));
- ((markobj) (window->has_modeline_p));
- ((markobj) (window->modeline_shadow_thickness));
- ((markobj) (window->scrollbar_width));
- ((markobj) (window->scrollbar_height));
- ((markobj) (window->left_margin_width));
- ((markobj) (window->right_margin_width));
- ((markobj) (window->toolbar_size[0]));
- ((markobj) (window->toolbar_size[1]));
- ((markobj) (window->toolbar_size[2]));
- ((markobj) (window->toolbar_size[3]));
- ((markobj) (window->minimum_line_ascent));
- ((markobj) (window->minimum_line_descent));
- ((markobj) (window->use_left_overflow));
- ((markobj) (window->use_right_overflow));
- ((markobj) (window->menubar_visible_p));
- ((markobj) (window->toolbar_buttons_captioned_p));
- /* End cached specifiers. */
- ((markobj) (window->dedicated));
- mark_face_cache_elements (window->face_cache_elements, markobj);
- mark_glyph_cache_elements (window->glyph_cache_elements, markobj);
- return (Qnil);
- }
-
- static void
- print_window (Lisp_Object obj, Lisp_Object printcharfun, int escapeflag)
- {
- char buf[200];
-
- if (print_readably)
- error ("printing unreadable object #<window 0x%x>",
- XWINDOW (obj)->header.uid);
-
- write_c_string ("#<window", printcharfun);
- if (!NILP (XWINDOW (obj)->buffer))
- {
- Lisp_Object name = XBUFFER (XWINDOW (obj)->buffer)->name;
- write_c_string (" on ", printcharfun);
- print_internal (name, printcharfun, 1);
- }
- sprintf (buf, " 0x%x>", XWINDOW (obj)->header.uid);
- write_c_string (buf, printcharfun);
- }
-
- static void
- finalize_window (void *header, int for_disksave)
- {
- struct window *w = (struct window *) header;
-
- if (w->line_start_cache)
- {
- Dynarr_free (w->line_start_cache);
- w->line_start_cache = 0;
- }
-
- if (w->face_cache_elements)
- {
- Dynarr_free (w->face_cache_elements);
- w->face_cache_elements = 0;
- }
-
- if (w->glyph_cache_elements)
- {
- Dynarr_free (w->glyph_cache_elements);
- w->glyph_cache_elements = 0;
- }
- }
-
- #define INIT_DISP_VARIABLE(field, initialization) \
- p->field[CURRENT_DISP] = initialization; \
- p->field[DESIRED_DISP] = initialization; \
- p->field[CMOTION_DISP] = initialization;
-
- /* We have an implicit assertion that the first two elements (default
- and modeline faces) are always present in the face_element_cache.
- Normally redisplay ensures this. However, it is possible for a
- window to get created and functions which reference these values
- called before redisplay works with the window for the first time.
- All callers of allocate_window should therefore call
- reset_face_cache_elements on the created window. We can't do it
- here because the window must have its frame pointer set or
- reset_face_cache_elements will fail. */
- Lisp_Object
- allocate_window (void)
- {
- Lisp_Object val = Qnil;
- struct window *p = alloc_lcrecord (sizeof (struct window),
- lrecord_window);
-
- XSETWINDOW (val, p);
-
- p->dead = 0;
- p->frame = Qnil;
- p->mini_p = Qnil;
- p->next = Qnil;
- p->prev = Qnil;
- p->hchild = Qnil;
- p->vchild = Qnil;
- p->parent = Qnil;
- p->pixel_left = 0;
- p->pixel_top = 0;
- p->pixel_height = 0;
- p->pixel_width = 0;
- p->buffer = Qnil;
- INIT_DISP_VARIABLE (start, Fmake_marker ());
- INIT_DISP_VARIABLE (pointm, Fmake_marker ());
- p->sb_point = Fmake_marker ();
- p->force_start = 0;
- p->hscroll = 0;
- p->use_time = Qzero;
- INIT_DISP_VARIABLE (last_modified, Qzero);
- INIT_DISP_VARIABLE (last_point, Fmake_marker ());
- INIT_DISP_VARIABLE (last_start, Fmake_marker ());
- INIT_DISP_VARIABLE (last_facechange, Qzero);
- p->face_cache_elements = Dynarr_new (struct face_cache_element);
- p->glyph_cache_elements = Dynarr_new (struct glyph_cache_element);
- p->line_start_cache = Dynarr_new (struct line_start_cache);
- p->line_cache_last_updated = Qzero;
- p->line_cache_validation_override = 0;
- p->max_line_len = 0;
- p->config_mark = 0;
- INIT_DISP_VARIABLE (last_point_x, 0);
- INIT_DISP_VARIABLE (last_point_y, 0);
- INIT_DISP_VARIABLE (window_end_pos, 0);
- p->redo_modeline = 0;
- p->start_at_line_beg = 0;
- /* cached specifier values: will get set properly later */
- p->display_table = Qnil;
- p->has_modeline_p = Qnil;
- p->modeline_shadow_thickness = Qnil;
- p->scrollbar_width = Qnil;
- p->scrollbar_height = Qnil;
- p->left_margin_width = Qnil;
- p->right_margin_width = Qnil;
- p->toolbar_size[0] = Qnil;
- p->toolbar_size[1] = Qnil;
- p->toolbar_size[2] = Qnil;
- p->toolbar_size[3] = Qnil;
- p->minimum_line_ascent = Qnil;
- p->minimum_line_descent = Qnil;
- p->use_left_overflow = Qnil;
- p->use_right_overflow = Qnil;
- p->menubar_visible_p = Qnil;
- p->toolbar_buttons_captioned_p = Qnil;
- /* end cached specifier values. */
-
- p->dedicated = Qnil;
- p->windows_changed = 1;
- p->shadow_thickness_changed = 1;
-
- return (val);
- }
- #undef INIT_DISP_VARIABLE
-
- /*
- * The redisplay structures used to be stored with each window. While
- * they are logically something associated with frames they can't be
- * stored there with a redisplay which handles variable height lines.
- * Lines in horizontally split windows might not line up. So they get
- * stored with the windows.
- *
- * The problem with this is window configurations. When restoring a
- * window configuration it now becomes problematic to do an
- * incremental redisplay. The solution is to store the redisplay
- * structures with the frame as they should be but laid out in the
- * same manner as the window structure. Thus is born the window
- * mirror.
- *
- * It also becomes a convenient place to stick scrollbar instances
- * since they extrapolate out to having the same problem described for
- * the display structures.
- */
-
- /* Create a new mindow mirror structure and associated redisplay
- structs. */
- static struct window_mirror *
- new_window_mirror (struct frame *f)
- {
- struct window_mirror *t;
-
- t = (struct window_mirror *)
- xmalloc (sizeof (struct window_mirror));
- memset (t, 0, sizeof (struct window_mirror));
-
- t->frame = f;
-
- t->current_display_lines = Dynarr_new (struct display_line);
- t->desired_display_lines = Dynarr_new (struct display_line);
- t->cmotion_display_lines = Dynarr_new (struct display_line);
- t->buffer = NULL;
-
- t->scrollbar_vertical_instance = NULL;
- t->scrollbar_horizontal_instance = NULL;
-
- return t;
- }
-
- /* Synchronize the mirror structure with a given window structure.
- This is normally called from update_frame_window_mirror with a
- starting window of f->root_window. */
- static struct window_mirror *
- update_mirror_internal (Lisp_Object win, struct window_mirror *mir)
- {
- if (NILP (win))
- {
- if (mir)
- {
- free_window_mirror (mir);
- mir = 0;
- }
- return mir;
- }
- else
- if (!mir)
- mir = new_window_mirror (XFRAME (XWINDOW (win)->frame));
-
- mir->next = update_mirror_internal (XWINDOW (win)->next, mir->next);
- mir->hchild = update_mirror_internal (XWINDOW (win)->hchild, mir->hchild);
- mir->vchild = update_mirror_internal (XWINDOW (win)->vchild, mir->vchild);
-
- /*
- * If the redisplay structs are not empty and the mirror has
- * children, then this mirror structure was formerly being used for
- * display but is no longer. Reset its current display structs so
- * that redisplay doesn't accidentally think they are accurate if it
- * is later used for display purposes once again. Also, mark the
- * scrollbar instance as not active.
- */
- if (mir->vchild || mir->hchild)
- {
- /* Reset both sets of lines. The assertion is that outside of
- redisplay, these are always identical. */
- Dynarr_reset (mir->current_display_lines);
- Dynarr_reset (mir->desired_display_lines);
- update_window_scrollbars (XWINDOW (win), mir, 0, 0);
- mir->buffer = NULL;
- }
-
- return mir;
- }
-
- /* Given a window mirror, determine which real window it contains the
- redisplay structures for. */
- static Lisp_Object
- real_window_internal (Lisp_Object win, struct window_mirror *rmir,
- struct window_mirror *mir)
- {
- Lisp_Object retval;
-
- for (; !NILP (win) && rmir ; win = XWINDOW (win)->next, rmir = rmir->next)
- {
- if (mir == rmir)
- return win;
- if (!NILP (XWINDOW (win)->vchild))
- {
- retval = real_window_internal (XWINDOW (win)->vchild, rmir->vchild,
- mir);
- if (!NILP (retval))
- return retval;
- }
- if (!NILP (XWINDOW (win)->hchild))
- {
- retval = real_window_internal (XWINDOW (win)->hchild, rmir->hchild,
- mir);
- if (!NILP (retval))
- return retval;
- }
- }
-
- return Qnil;
- }
-
- /* Given a real window, find the mirror structure which contains its
- redisplay structures. */
- static struct window_mirror *
- find_window_mirror_internal (Lisp_Object win, struct window_mirror *rmir,
- struct window *w)
- {
- struct window_mirror *retval;
-
- for (; !NILP (win); win = XWINDOW (win)->next, rmir = rmir->next)
- {
- if (w == XWINDOW (win))
- return rmir;
- if (!NILP (XWINDOW (win)->vchild) &&
- (retval = find_window_mirror_internal (XWINDOW (win)->vchild,
- rmir->vchild, w)))
- return retval;
- if (!NILP (XWINDOW (win)->hchild) &&
- (retval = find_window_mirror_internal (XWINDOW (win)->hchild,
- rmir->hchild, w)))
- return retval;
- }
-
- return 0;
- }
-
- /* Update the mirror structure for the given frame. */
- void
- update_frame_window_mirror (struct frame *f)
- {
- f->root_mirror = update_mirror_internal (f->root_window, f->root_mirror);
- f->mirror_dirty = 0;
- }
-
- /* Free a given mirror structure along with all of its children as
- well as their associated display structures. */
- void
- free_window_mirror (struct window_mirror *mir)
- {
- struct window_mirror *p;
-
- p = mir;
- while (mir)
- {
- if (mir->hchild) free_window_mirror (mir->hchild);
- if (mir->vchild) free_window_mirror (mir->vchild);
- release_window_mirror_scrollbars (mir);
- free_display_structs (mir);
- mir = mir->next;
- xfree (p);
- p = mir;
- }
- }
-
- /* Given a mirror structure, return the window it mirrors. Calls
- real_window_internal to do most of the work. */
- Lisp_Object
- real_window (struct window_mirror *mir, int no_abort)
- {
- Lisp_Object retval;
-
- retval = real_window_internal (mir->frame->root_window,
- mir->frame->root_mirror, mir);
-
- if (NILP (retval) && !no_abort)
- abort ();
-
- return retval;
- }
-
- /* Given a real window, return its mirror structure. Calls
- find_window_mirror_internal to do all of the work. */
- struct window_mirror *
- find_window_mirror (struct window *w)
- {
- struct frame *f = XFRAME (w->frame);
- if (f->mirror_dirty)
- update_frame_window_mirror (f);
- return find_window_mirror_internal (f->root_window, f->root_mirror, w);
- }
-
- /*****************************************************************************
- find_window_by_pixel_pos
-
- Given a pixel position relative to a frame, find the window at that
- position.
- ****************************************************************************/
- struct window *
- find_window_by_pixel_pos (unsigned int pix_x, unsigned int pix_y,
- Lisp_Object win)
- {
- struct window *w;
-
- if (NILP (win))
- return 0;
-
- for (; !NILP (win); win = XWINDOW (win)->next)
- {
- if (!NILP (XWINDOW (win)->vchild) &&
- (w = find_window_by_pixel_pos (pix_x, pix_y, XWINDOW (win)->vchild)))
- return w;
- if (!NILP (XWINDOW (win)->hchild) &&
- (w = find_window_by_pixel_pos (pix_x, pix_y, XWINDOW (win)->hchild)))
- return w;
- w = XWINDOW (win);
- if (pix_x >= WINDOW_LEFT (w)
- && pix_x <= WINDOW_RIGHT (w)
- && pix_y >= WINDOW_TOP (w)
- && pix_y <= WINDOW_BOTTOM (w))
- return w;
- }
- return 0;
- }
-
- /* Return a pointer to the display structures for the given window. */
- display_line_dynarr *
- window_display_lines (struct window *w, int which)
- {
- struct window_mirror *t;
-
- if (XFRAME (w->frame)->mirror_dirty)
- update_frame_window_mirror (XFRAME (w->frame));
- t = find_window_mirror (w);
- if (!t)
- abort ();
-
- if (which == CURRENT_DISP)
- return t->current_display_lines;
- else if (which == DESIRED_DISP)
- return t->desired_display_lines;
- else if (which == CMOTION_DISP)
- return t->cmotion_display_lines;
- else
- abort ();
-
- return 0; /* shut up compiler */
- }
-
- struct buffer *
- window_display_buffer (struct window *w)
- {
- struct window_mirror *t;
-
- if (XFRAME (w->frame)->mirror_dirty)
- update_frame_window_mirror (XFRAME (w->frame));
- t = find_window_mirror (w);
- if (!t)
- abort ();
-
- return t->buffer;
- }
-
- void
- set_window_display_buffer (struct window *w, struct buffer *b)
- {
- struct window_mirror *t;
-
- if (XFRAME (w->frame)->mirror_dirty)
- update_frame_window_mirror (XFRAME (w->frame));
- t = find_window_mirror (w);
- if (!t)
- abort ();
-
- t->buffer = b;
- }
-
-
- /* Determining a windows position based solely on its pixel
- positioning doesn't work. Instead, we do it the intelligent way,
- by checking its positioning in the window hierarchy. */
- int
- window_is_leftmost (struct window *w)
- {
- Lisp_Object parent, current_ancestor, window;
-
- XSETWINDOW (window, w);
-
- parent = XWINDOW (window)->parent;
- current_ancestor = window;
-
- while (!NILP (parent))
- {
- if (!NILP (XWINDOW (parent)->hchild) &&
- !EQ (XWINDOW (parent)->hchild, current_ancestor))
- return 0;
-
- current_ancestor = parent;
- parent = XWINDOW (parent)->parent;
- }
-
- return 1;
- }
-
- int
- window_is_rightmost (struct window *w)
- {
- Lisp_Object parent, current_ancestor, window;
-
- XSETWINDOW (window, w);
-
- parent = XWINDOW (window)->parent;
- current_ancestor = window;
-
- while (!NILP (parent))
- {
- if (!NILP (XWINDOW (parent)->hchild)
- && !NILP (XWINDOW (current_ancestor)->next))
- return 0;
-
- current_ancestor = parent;
- parent = XWINDOW (parent)->parent;
- }
-
- return 1;
- }
-
- int
- window_truncation_on (struct window *w)
- {
- /* Horizontally scrolled windows are truncated. */
- if (w->hscroll)
- return 1;
-
- /* If truncate_partial_width_windows is true and the window is not
- the full width of the frame it is truncated. */
- if (truncate_partial_width_windows
- && !(window_is_leftmost (w) && window_is_rightmost (w)))
- return 1;
-
- /* If the window's buffer's value of truncate_lines is non-nil, then
- the window is truncated. */
- if (!NILP (XBUFFER (w->buffer)->truncate_lines))
- return 1;
-
- return 0;
- }
-
- int
- window_needs_vertical_divider (struct window *w)
- {
- struct frame *f = XFRAME (w->frame);
-
- if (!window_scrollbar_width (w))
- {
- if (f->scrollbar_on_left)
- return (!window_is_leftmost (w));
- else
- return (!window_is_rightmost (w));
- }
- else
- return 0;
- }
-
- int
- window_scrollbar_width (struct window *w)
- {
- if (WINDOW_IS_TTY (w)
- || MINI_WINDOW_P (w)
- || NILP (w->buffer))
- /* #### when does NILP (w->buffer) happen? */
- return 0;
-
- return XINT (w->scrollbar_width);
- }
-
- /* Horizontal scrollbars are only active on windows with truncation
- turned on. */
- int
- window_scrollbar_height (struct window *w)
- {
- if (WINDOW_IS_TTY (w)
- || MINI_WINDOW_P (w)
- || NILP (w->buffer)
- || !window_truncation_on (w))
- return 0;
-
- return XINT (w->scrollbar_height);
- }
-
- /* #### When we finally get embedded faces in the modeline, this
- function will need to get smarter. */
- int
- window_modeline_height (struct window *w)
- {
- struct frame *f = XFRAME (w->frame);
- struct device *d = XDEVICE (f->device);
- int modeline_height;
-
- if (MINI_WINDOW_P (w) || NILP (w->buffer))
- {
- modeline_height = 0;
- }
- else if (!WINDOW_HAS_MODELINE_P (w))
- {
- if (window_scrollbar_height (w))
- modeline_height = 0;
- else
- {
- modeline_height = DEVMETH (d, divider_height, ());
-
- if (!EQ (Qzero, w->modeline_shadow_thickness) && FRAME_IS_WIN (f))
- modeline_height += (2 * MODELINE_SHADOW_THICKNESS (w));
- }
- }
- else
- {
- struct font_metric_info fm;
-
- if (noninteractive)
- modeline_height = 0;
- else
- {
- DEVMETH (d, font_metric_info,
- (d, FACE_CACHE_ELEMENT_FONT (w, MODELINE_INDEX), &fm));
- modeline_height = fm.ascent + fm.descent;
-
- if (!EQ (Qzero, w->modeline_shadow_thickness) && FRAME_IS_WIN (f))
- modeline_height += (2 * MODELINE_SHADOW_THICKNESS (w));
- }
- }
-
- return modeline_height;
- }
-
- /*****************************************************************************
- margin_width_internal
-
- For a given window, return the width in pixels of the specified margin.
- ****************************************************************************/
- static int
- margin_width_internal (struct window *w, int left_margin)
- {
- struct buffer *b;
- struct frame *f = XFRAME (w->frame);
- struct device *d = XDEVICE (f->device);
- struct font_metric_info fm;
- int window_cwidth = window_char_width (w, 1);
- int margin_cwidth;
-
- /* We might be getting called on a non-leaf. */
- if (NILP (w->buffer))
- return 0;
-
- /* The minibuffer never has margins. */
- if (MINI_WINDOW_P (w))
- return 0;
-
- b = XBUFFER (w->buffer);
- margin_cwidth = (left_margin ? XINT (w->left_margin_width) :
- XINT (w->right_margin_width));
-
- /* We need the default character width. */
- DEVMETH (d, font_metric_info, (d, FACE_CACHE_ELEMENT_FONT (w, DEFAULT_INDEX),
- &fm));
-
- /* The left margin takes precedence over the right margin so we
- subtract its width from the space available for the right
- margin. */
- if (!left_margin)
- window_cwidth -= XINT (w->left_margin_width);
-
- /* The margin cannot be wider than the window is. We allow the
- value to be bigger since it is possible for the user to enlarge
- the window such that the left margin value would no longer be too
- big, but we won't return a value that is larger. */
- if (margin_cwidth > window_cwidth)
- margin_cwidth = window_cwidth;
-
- /* At the user level the margin is always specified in characters.
- Internally however it is manipulated in terms of pixels. */
- return (margin_cwidth * fm.width);
- }
-
- int
- window_left_margin_width (struct window *w)
- {
- return margin_width_internal (w, 1);
- }
-
- int
- window_right_margin_width (struct window *w)
- {
- return margin_width_internal (w, 0);
- }
-
- static int
- window_top_toolbar_height (struct window *w)
- {
- /* #### implement this shit. */
- return 0;
- }
-
- /* #### Currently used in scrollbar.c. Does it actually need to be? */
- int
- window_bottom_toolbar_height (struct window *w)
- {
- return 0;
- }
-
- static int
- window_left_toolbar_width (struct window *w)
- {
- return 0;
- }
-
- static int
- window_right_toolbar_width (struct window *w)
- {
- return 0;
- }
-
- /*****************************************************************************
- Window Gutters
-
- The gutters of a window are those areas in the boundary defined by
- w->pixel_top, w->pixel_left, w->pixel_height and w->pixel_width which
- do not contain text. Items which may be in the gutters include
- scrollbars, toolbars and modelines. The margin areas are not
- included. This is an exception made because redisplay special cases
- the handling of those areas in many places in such a way that
- including them in the gutter area would make life difficult.
-
- The size functions refer to height for the bottom and top gutters and
- width for the left and right gutters. The starting position
- functions refer to the Y coord for bottom and top gutters and the X
- coord for left and right gutters. All starting positions are
- relative to the frame, not the window.
- ****************************************************************************/
-
- int
- window_top_gutter_height (struct window *w)
- {
- struct frame *f = XFRAME (w->frame);
- int toolbar_height = window_top_toolbar_height (w);
-
- if (!NILP (w->hchild) || !NILP (w->vchild))
- return 0;
-
- if (f->scrollbar_on_top)
- return window_scrollbar_height (w) + toolbar_height;
- else
- return toolbar_height;
- }
-
- int
- window_bottom_gutter_height (struct window *w)
- {
- struct frame *f = XFRAME (w->frame);
- int other_height;
-
- if (!NILP (w->hchild) || !NILP (w->vchild))
- return 0;
- else
- other_height =
- window_modeline_height (w) + window_bottom_toolbar_height (w);
-
- if (!f->scrollbar_on_top)
- return window_scrollbar_height (w) + other_height;
- else
- return other_height;
- }
-
- static int
- window_left_right_gutter_width_internal (struct window *w, int modeline)
- {
- struct device *d = XDEVICE (XFRAME (w->frame)->device);
- int scrollbar_width = window_scrollbar_width (w);
-
- if (!NILP (w->hchild) || !NILP (w->vchild))
- return 0;
-
- if (!modeline)
- {
- if (scrollbar_width)
- return scrollbar_width;
- else if (window_needs_vertical_divider (w))
- return DEVMETH (d, divider_width, ());
- else
- return 0;
- }
- else
- {
- /* The shadows on the 3D modelines provide a visual break
- between the modelines of horizontally split windows. 2D
- modelines need some help, though. */
- if (!EQ (Qzero, w->modeline_shadow_thickness))
- return 0;
- else if (window_needs_vertical_divider (w))
- return DEVMETH (d, divider_width, ());
- else
- return 0;
- }
- }
-
- int
- window_left_gutter_width (struct window *w, int modeline)
- {
- struct frame *f = XFRAME (w->frame);
-
- if (!NILP (w->hchild) || !NILP (w->vchild))
- return 0;
-
- if (f->scrollbar_on_left)
- {
- return (window_left_right_gutter_width_internal (w, modeline) +
- window_left_toolbar_width (w));
- }
- else
- return window_left_toolbar_width (w);
- }
-
- int
- window_right_gutter_width (struct window *w, int modeline)
- {
- struct frame *f = XFRAME (w->frame);
-
- if (!NILP (w->hchild) || !NILP (w->vchild))
- return 0;
-
- if (!f->scrollbar_on_left)
- {
- return (window_left_right_gutter_width_internal (w, modeline) +
- window_right_toolbar_width (w));
- }
- else
- return window_right_toolbar_width (w);
- }
-
-
- DEFUN ("selected-window", Fselected_window, Sselected_window, 0, 1, 0,
- "Return the window that the cursor now appears in and commands apply to.\n\
- If DEVICE is not specified, the selected device is used.")
- (device)
- Lisp_Object device;
- {
- Lisp_Object frame;
-
- if (NILP (device) && NILP (Fselected_device ()))
- return Qnil; /* happens at startup */
-
- XSETDEVICE (device, get_device (device));
- frame = Fselected_frame (device);
- if (NILP (frame))
- return Qnil;
- else
- return FRAME_SELECTED_WINDOW (XFRAME (frame));
- }
-
- DEFUN ("minibuffer-window", Fminibuffer_window, Sminibuffer_window, 0, 1, 0,
- "Return the window used now for minibuffers.\n\
- If the optional argument DEV-OR-FRAME is specified and is a frame, return\n\
- the minibuffer window used by that frame. If DEV-OR-FRAME is a device,\n\
- then the selected frame on that device will be used. Otherwise, the\n\
- selected frame on the current device is assumed.")
- (dev_or_frame)
- Lisp_Object dev_or_frame;
- {
- Lisp_Object result;
- struct frame *f;
-
- if (DEVICEP (dev_or_frame))
- f = device_selected_frame (XDEVICE (dev_or_frame));
- else
- f = get_frame (dev_or_frame);
-
- result = FRAME_MINIBUF_WINDOW (f);
- if (WINDOWP (result))
- return (result);
-
- choose_minibuf_frame (); /*#### Is this crock needed here??? */
-
- return (minibuf_window);
- }
-
- DEFUN ("window-minibuffer-p", Fwindow_minibuffer_p, Swindow_minibuffer_p, 1, 1, 0,
- "Return non-nil if WINDOW is a minibuffer window.")
- (window)
- Lisp_Object window;
- {
- struct window *w = decode_window (window);
- return (MINI_WINDOW_P (w) ? Qt : Qnil);
- }
-
- DEFUN ("window-lowest-p", Fwindow_lowest_p, Swindow_lowest_p, 1, 1, 0,
- "Return non-nil if WINDOW is along the bottom of its frame.")
- (window)
- Lisp_Object window;
- {
- struct window *w = decode_window (window);
- int offset;
- Lisp_Object cur_window;
-
- XSETWINDOW (window, w);
-
- /* Fframe_lowest_window returns nil once the offset is greater than
- the number of windows along the bottom. */
- offset = 0;
- do
- {
- cur_window = Fframe_lowest_window (w->frame, make_number (offset));
-
- if (EQ (cur_window, window))
- return Qt;
- offset++;
- }
- while (!NILP (cur_window));
-
- return Qnil;
- }
-
- DEFUN ("window-highest-p", Fwindow_highest_p, Swindow_highest_p, 1, 1, 0,
- "Return non-nil if WINDOW is along the top of its frame.")
- (window)
- Lisp_Object window;
- {
- struct window *w = decode_window (window);
- int offset;
- Lisp_Object cur_window;
-
- XSETWINDOW (window, w);
-
- /* Fframe_highest_window returns nil once the offset is greater than
- the number of windows along the top. */
- offset = 0;
- do
- {
- cur_window = Fframe_highest_window (w->frame, make_number (offset));
-
- if (EQ (cur_window, window))
- return Qt;
- offset++;
- }
- while (!NILP (cur_window));
-
- return Qnil;
- }
-
- DEFUN ("pos-visible-in-window-p", Fpos_visible_in_window_p,
- Spos_visible_in_window_p, 0, 2, 0,
- "Return t if position POS is currently on the frame in WINDOW.\n\
- Returns nil if that position is scrolled vertically out of view.\n\
- POS defaults to point in WINDOW's buffer; WINDOW, to the selected window.")
- (pos, window)
- Lisp_Object pos, window;
- {
- struct window *w;
- Bufpos top;
- Bufpos posint;
- struct buffer *buf;
-
- w = decode_window (window);
- top = marker_position (w->start[CURRENT_DISP]);
-
- buf = XBUFFER (w->buffer);
-
- if (NILP (pos))
- posint = BUF_PT (buf);
- else
- {
- CHECK_INT_COERCE_MARKER (pos, 0);
- posint = XINT (pos);
- }
-
- if (posint < top || posint > BUF_ZV (buf))
- return Qnil;
-
- /* w->start can be out of range. If it is, do something reasonable. */
- if (top < BUF_BEGV (buf) || top > BUF_ZV (buf))
- return Qnil;
-
- if (point_would_be_visible (w, top, posint))
- return Qt;
- else
- return Qnil;
- }
-
-
- struct window *
- decode_window (Lisp_Object window)
- {
- if (NILP (window))
- return XWINDOW (Fselected_window (Qnil));
-
- CHECK_LIVE_WINDOW (window, 0);
- return XWINDOW (window);
- }
-
- DEFUN ("window-buffer", Fwindow_buffer, Swindow_buffer, 0, 1, 0,
- "Return the buffer that WINDOW is displaying.")
- (window)
- Lisp_Object window;
- {
- return decode_window (window)->buffer;
- }
-
- DEFUN ("window-frame", Fwindow_frame, Swindow_frame, 0, 1, 0,
- "Return the frame that window WINDOW is on.")
- (window)
- Lisp_Object window;
- {
- return decode_window (window)->frame;
- }
-
- DEFUN ("window-height", Fwindow_height, Swindow_height, 0, 1, 0,
- "Return the number of lines in WINDOW (including its modeline).")
- (window)
- Lisp_Object window;
- {
- return make_number (window_char_height (decode_window (window), 1));
- }
-
- DEFUN ("window-pixel-height", Fwindow_pixel_height, Swindow_pixel_height,
- 0, 1, 0,
- "Return the height of WINDOW in pixels. Defaults to current window.")
- (window)
- Lisp_Object window;
- {
- return (make_number (decode_window (window)->pixel_height));
- }
-
- DEFUN ("window-width", Fwindow_width, Swindow_width, 0, 1, 0,
- "Return the number of display columns in WINDOW.\n\
- This is the width that is usable columns available for text in WINDOW.")
- (window)
- Lisp_Object window;
- {
- struct window *w = decode_window (window);
- return (make_number (window_char_width (w, 0)));
- }
-
- DEFUN ("window-pixel-width", Fwindow_pixel_width, Swindow_pixel_width,
- 0, 1, 0,
- "Return the width of WINDOW in pixels. Defaults to current window.")
- (window)
- Lisp_Object window;
- {
- return (make_number (decode_window (window)->pixel_width));
- }
-
- DEFUN ("window-hscroll", Fwindow_hscroll, Swindow_hscroll, 0, 1, 0,
- "Return the number of columns by which WINDOW is scrolled from left margin.")
- (window)
- Lisp_Object window;
- {
- return (make_number (decode_window (window)->hscroll));
- }
-
- DEFUN ("set-window-hscroll", Fset_window_hscroll, Sset_window_hscroll, 2, 2, 0,
- "Set number of columns WINDOW is scrolled from left margin to NCOL.\n\
- NCOL should be zero or positive.")
- (window, ncol)
- Lisp_Object window, ncol;
- {
- struct window *w;
- int ncols;
-
- CHECK_INT (ncol, 1);
- ncols = XINT (ncol);
- if (ncols < 0) ncols = 0;
- if (ncols >= (1 << (SHORTBITS - 1)))
- args_out_of_range (ncol, Qnil);
- w = decode_window (window);
- if (w->hscroll != ncols)
- MARK_CLIP_CHANGED;
- w->hscroll = ncols;
- return ncol;
- }
-
- DEFUN ("window-pixel-edges", Fwindow_pixel_edges, Swindow_pixel_edges,
- 0, 1, 0,
- "Return a list of the pixel edge coordinates of WINDOW.\n\
- \(LEFT TOP RIGHT BOTTOM), all relative to 0, 0 at top left corner of frame.\n\
- The frame toolbars and menubars are considered to be outside of this area.")
- (window)
- Lisp_Object window;
- {
- struct window *w = decode_window (window);
- struct frame *f = XFRAME (w->frame);
- int left, top;
-
- left = w->pixel_left - FRAME_LEFT_BORDER_END (f);
- top = w->pixel_top - FRAME_TOP_BORDER_END (f);
-
- return list4 (make_number (left),
- make_number (top),
- make_number (left + w->pixel_width),
- make_number (top + w->pixel_height));
- }
-
- DEFUN ("window-point", Fwindow_point, Swindow_point, 0, 1, 0,
- "Return current value of point in WINDOW.\n\
- For a nonselected window, this is the value point would have\n\
- if that window were selected.\n\
- \n\
- Note that, when WINDOW is the selected window and its buffer\n\
- is also currently selected, the value returned is the same as (point).\n\
- It would be more strictly correct to return the `top-level' value\n\
- of point, outside of any save-excursion forms.\n\
- But that is hard to define.")
- (window)
- Lisp_Object window;
- {
- struct window *w = decode_window (window);
-
- /* The special check for current buffer is necessary for this
- function to work as defined when called within an excursion. */
- if (w == XWINDOW (Fselected_window (XFRAME (w->frame)->device))
- && current_buffer == XBUFFER (w->buffer))
- return Fpoint (Qnil);
- return Fmarker_position (w->pointm[CURRENT_DISP]);
- }
-
- DEFUN ("window-start", Fwindow_start, Swindow_start, 0, 1, 0,
- "Return position at which display currently starts in WINDOW.")
- (window)
- Lisp_Object window;
- {
- return Fmarker_position (decode_window (window)->start[CURRENT_DISP]);
- }
-
- DEFUN ("window-end", Fwindow_end, Swindow_end, 0, 2, 0,
- "Return position at which display currently ends in WINDOW.\n\
- This is updated by redisplay, when it runs to completion.\n\
- Simply changing the buffer text or setting `window-start'\n\
- does not update this value.\n\
- If GUARANTEE is non-nil, then the return value is guaranteed to be\n\
- the value of window-end at the end of the next full redisplay assuming\n\
- nothing else changes in the meantime. This function is potentially much\n\
- slower with this flag set.")
- (window, guarantee)
- Lisp_Object window, guarantee;
- {
- Lisp_Object value;
- struct window *w = decode_window (window);
- Lisp_Object buf;
-
- if (NILP (guarantee))
- {
- buf = w->buffer;
- CHECK_BUFFER (buf, 0);
-
- XSETINT (value, BUF_Z (XBUFFER (buf)) - w->window_end_pos[CURRENT_DISP]);
-
- return value;
- }
- else
- {
- Bufpos startp = marker_position (w->start[CURRENT_DISP]);
- return (make_number (end_of_last_line (w, startp)));
- }
- }
-
- DEFUN ("set-window-point", Fset_window_point, Sset_window_point, 2, 2, 0,
- "Make point value in WINDOW be at position POS in WINDOW's buffer.")
- (window, pos)
- Lisp_Object window, pos;
- {
- struct window *w = decode_window (window);
-
- CHECK_INT_COERCE_MARKER (pos, 1);
- if (w == XWINDOW (Fselected_window (Qnil)))
- Fgoto_char (pos, Fcurrent_buffer ());
- else
- set_marker_restricted (w->pointm[CURRENT_DISP], pos, w->buffer);
-
- MARK_POINT_CHANGED;
- return pos;
- }
-
- DEFUN ("set-window-start", Fset_window_start, Sset_window_start, 2, 3, 0,
- "Make display in WINDOW start at position POS in WINDOW's buffer.\n\
- Optional third arg NOFORCE non-nil inhibits next redisplay\n\
- from overriding motion of point in order to display at this exact start.")
- (window, pos, noforce)
- Lisp_Object window, pos, noforce;
- {
- struct window *w = decode_window (window);
-
- CHECK_INT_COERCE_MARKER (pos, 1);
- set_marker_restricted (w->start[CURRENT_DISP], pos, w->buffer);
- /* this is not right, but much easier than doing what is right. */
- w->start_at_line_beg = 0;
- if (NILP (noforce))
- w->force_start = 1;
- w->redo_modeline = 1;
- SET_LAST_MODIFIED (w, 0);
- SET_LAST_FACECHANGE (w);
-
- MARK_WINDOWS_CHANGED(w);
-
- return pos;
- }
-
- DEFUN ("window-dedicated-p", Fwindow_dedicated_p, Swindow_dedicated_p,
- 1, 1, 0,
- "Return WINDOW's dedicated object, usually t or nil.\n\
- See also `set-window-buffer-dedicated'.")
- (window)
- Lisp_Object window;
- {
- return decode_window (window)->dedicated;
- }
-
- DEFUN ("set-window-buffer-dedicated", Fset_window_buffer_dedicated,
- Sset_window_buffer_dedicated, 2, 2, 0,
- "Make WINDOW display BUFFER and be dedicated to that buffer.\n\
- Then Emacs will not automatically change which buffer appears in WINDOW.\n\
- If BUFFER is nil, make WINDOW not be dedicated (but don't change which\n\
- buffer appears in it currently).")
- (window, buffer)
- Lisp_Object window, buffer;
- {
- /* This function can GC */
- struct window *w = decode_window (window);
-
- if (NILP (buffer))
- w->dedicated = Qnil;
- else
- {
- /* Allow non-buffer argument for FSF compatibility. */
- if (BUFFERP (buffer))
- Fset_window_buffer (window, Fget_buffer_create (buffer));
- w->dedicated = Qt;
- }
-
- return w->dedicated;
- }
-
-
- /* Record info on buffer window w is displaying
- when it is about to cease to display that buffer. */
- static void
- unshow_buffer (struct window *w)
- {
- Lisp_Object buf = w->buffer;
-
- if (XBUFFER (buf) != XMARKER (w->pointm[CURRENT_DISP])->buffer)
- abort ();
-
- #ifdef ENERGIZE
- energize_buffer_hidden_hook (w);
- #endif
-
- /* FSF disables this check, so I'll do it too. I hope it won't
- break things. --ben */
- #if 0
- if (w == XWINDOW (Fselected_window (Qnil))
- || ! EQ (buf, XWINDOW (Fselected_window (Qnil))->buffer))
- /* Do this except when the selected window's buffer
- is being removed from some other window. */
- #endif
- /* last_window_start records the start position that this buffer
- had in the last window to be disconnected from it.
- Now that this statement is unconditional,
- it is possible for the buffer to be displayed in the
- selected window, while last_window_start reflects another
- window which was recently showing the same buffer.
- Some people might say that might be a good thing. Let's see. */
- XBUFFER (buf)->last_window_start =
- marker_position (w->start[CURRENT_DISP]);
-
- /* Point in the selected window's buffer
- is actually stored in that buffer, and the window's pointm isn't used.
- So don't clobber point in that buffer. */
- if (! EQ (buf, XWINDOW (Fselected_window (Qnil))->buffer))
- {
- struct buffer *b= XBUFFER (buf);
- BUF_SET_PT (b, bufpos_clip_to_bounds (BUF_BEGV (b),
- marker_position (w->pointm[CURRENT_DISP]),
- BUF_ZV (b)));
- }
- }
-
- /* Put REPLACEMENT into the window structure in place of OLD. */
- static void
- replace_window (Lisp_Object old, Lisp_Object replacement)
- {
- Lisp_Object tem;
- struct window *o = XWINDOW (old), *p = XWINDOW (replacement);
-
- /* If OLD is its frame's root_window, then replacement is the new
- root_window for that frame. */
-
- if (EQ (old, FRAME_ROOT_WINDOW (XFRAME (o->frame))))
- FRAME_ROOT_WINDOW (XFRAME (o->frame)) = replacement;
-
- WINDOW_LEFT (p) = WINDOW_LEFT (o);
- WINDOW_TOP (p) = WINDOW_TOP (o);
- WINDOW_WIDTH (p) = WINDOW_WIDTH (o);
- WINDOW_HEIGHT (p) = WINDOW_HEIGHT (o);
-
- p->next = tem = o->next;
- if (!NILP (tem))
- XWINDOW (tem)->prev = replacement;
-
- p->prev = tem = o->prev;
- if (!NILP (tem))
- XWINDOW (tem)->next = replacement;
-
- p->parent = tem = o->parent;
- if (!NILP (tem))
- {
- if (EQ (XWINDOW (tem)->vchild, old))
- XWINDOW (tem)->vchild = replacement;
- if (EQ (XWINDOW (tem)->hchild, old))
- XWINDOW (tem)->hchild = replacement;
- }
-
- /* #### Here, if replacement is a vertical combination
- and so is its new parent, we should make replacement's
- children be children of that parent instead. */
- }
-
- /* we're deleting W; set the structure of W to indicate this. */
-
- static void
- mark_window_as_deleted (struct window *w)
- {
- /* In the loop
- (while t (split-window) (delete-window))
- we end up with a tree of deleted windows which are all connected
- through the `next' slot. This might not seem so bad, as they're
- deleted, and will presumably be GCed - but if even *one* of those
- windows is still being pointed to, by the user, or by a window
- configuration, then *all* of those windows stick around.
-
- Since the window-configuration code doesn't need any of the
- pointers to other windows (they are all recreated from the
- window-config data), we set them all to nil so that we
- are able to collect more actual garbage.
- */
- w->next = Qnil;
- w->prev = Qnil;
- w->hchild = Qnil;
- w->vchild = Qnil;
- w->parent = Qnil;
-
- w->dead = 1;
-
- /* Free the extra data structures attached to windows immediately so
- they don't sit around consuming excess space. They will be
- reinitialized by the window-configuration code as necessary. */
- finalize_window ((void *) w, 0);
- }
-
- DEFUN ("delete-window", Fdelete_window, Sdelete_window, 0, 1, "",
- "Remove WINDOW from the display. Default is selected window.\n\
- If window is the only one on the frame, the frame is destroyed.")
- (window)
- Lisp_Object window;
- {
- /* This function can GC if this is the only window in the frame */
- struct window *w;
- Lisp_Object parent;
- struct window *par;
- Lisp_Object frame;
- struct frame *f;
- struct device *d;
-
- /* Note: this function is called by other C code on non-leaf
- windows. */
-
- /* Do the equivalent of decode_window() but don't error out on
- deleted window; it's OK to delete an already-deleted window. */
- if (NILP (window))
- window = Fselected_window (Qnil);
- else
- CHECK_WINDOW (window, 0);
- w = XWINDOW (window);
-
- /* It's okay to delete an already-deleted window. */
- if (! WINDOW_LIVE_P (w))
- return Qnil;
-
- frame = WINDOW_FRAME (w);
- f = XFRAME (frame);
- d = XDEVICE (FRAME_DEVICE (f));
-
- if (TOP_LEVEL_WINDOW_P (w))
- {
- if (NILP (memq_no_quit (frame, DEVICE_FRAME_LIST (d))))
- /* this frame isn't fully initialized yet; don't blow up. */
- return Qnil;
-
- if (MINI_WINDOW_P (XWINDOW (window)))
- error ("Attempt to delete the minibuffer window");
-
- /* It has been suggested that it's a good thing for C-x 0 to have this
- behavior, but not such a good idea for #'delete-window to have it.
- Maybe C-x 0 should be bound to something else, or maybe frame
- deletion should only happen when this is called interactively.
- */
- if (EQ (frame, next_frame (frame, Qt)))
- error ("Attempt to delete the only window on the only frame");
-
- MARK_FRAME_WINDOWS_STRUCTURE_CHANGED (f);
- delete_frame_internal (frame, 0);
- return Qnil;
- }
-
- /* At this point, we know the window has a parent. */
- parent = w->parent;
- par = XWINDOW (parent);
-
- MARK_FRAME_WINDOWS_STRUCTURE_CHANGED (f);
-
- /* Are we trying to delete any frame's selected window?
- Note that we could be dealing with a non-leaf window
- where the selected window is one of our children.
- So, we check by scanning all the ancestors of the
- frame's selected window and comparing each one with
- WINDOW. */
- {
- Lisp_Object pwindow;
-
- pwindow = FRAME_SELECTED_WINDOW (f);
-
- while (!NILP (pwindow))
- {
- if (EQ (window, pwindow))
- break;
- pwindow = XWINDOW (pwindow)->parent;
- }
-
- if (EQ (window, pwindow))
- {
- /* OK, we found it. */
- Lisp_Object alternative;
- alternative = Fnext_window (window, Qlambda, Qnil, Qnil);
-
- /* If we're about to delete the selected window on the
- selected frame, then we should use Fselect_window to select
- the new window. On the other hand, if we're about to
- delete the selected window on any other frame, we shouldn't do
- anything but set the frame's selected_window slot. */
- if (EQ (frame, Fselected_frame (Qnil)))
- Fselect_window (alternative);
- else
- FRAME_SELECTED_WINDOW (f) = alternative;
- }
- }
-
- /* w->buffer is nil in a non-leaf window; in this case,
- get rid of the markers we maintain that point into that buffer. */
- if (!NILP (w->buffer))
- {
- unshow_buffer (w);
- unchain_marker (w->pointm[CURRENT_DISP]);
- unchain_marker (w->pointm[DESIRED_DISP]);
- unchain_marker (w->pointm[CMOTION_DISP]);
- unchain_marker (w->start[CURRENT_DISP]);
- unchain_marker (w->start[DESIRED_DISP]);
- unchain_marker (w->start[CMOTION_DISP]);
- unchain_marker (w->sb_point);
- /* This breaks set-window-configuration if windows in the saved
- configuration get deleted and multiple frames are in use. */
- /* w->buffer = Qnil; */
- }
-
- /* close up the hole in the sibling list */
- if (!NILP (w->next))
- XWINDOW (w->next)->prev = w->prev;
- if (!NILP (w->prev))
- XWINDOW (w->prev)->next = w->next;
- if (EQ (window, par->hchild))
- par->hchild = w->next;
- if (EQ (window, par->vchild))
- par->vchild = w->next;
-
- /* Find one of our siblings to give our space to. */
- {
- Lisp_Object sib = w->prev;
- if (NILP (sib))
- {
- /* If w gives its space to its next sibling, that sibling needs
- to have its top/left side pulled back to where w's is.
- set_window_{height,width} will re-position the sibling's
- children. */
- sib = w->next;
- WINDOW_TOP (XWINDOW (sib)) = WINDOW_TOP (w);
- WINDOW_LEFT (XWINDOW (sib)) = WINDOW_LEFT (w);
- }
-
- /* Stretch that sibling. */
- if (!NILP (par->vchild))
- set_window_pixheight
- (sib, (WINDOW_HEIGHT (XWINDOW (sib)) + WINDOW_HEIGHT (w)), 1);
- if (!NILP (par->hchild))
- set_window_pixwidth
- (sib, (WINDOW_WIDTH (XWINDOW (sib)) + WINDOW_WIDTH (w)), 1);
- }
-
- /* If parent now has only one child,
- put the child into the parent's place. */
- {
- Lisp_Object parchild = par->hchild;
- if (NILP (parchild))
- parchild = par->vchild;
- if (NILP (XWINDOW (parchild)->next))
- {
- replace_window (parent, parchild);
- mark_window_as_deleted (XWINDOW (parent));
- }
- }
-
- /* Since we may be deleting combination windows, we must make sure that
- not only W but all its children have been marked as deleted. */
- if (!NILP (w->hchild))
- delete_all_subwindows (XWINDOW (w->hchild));
- else if (!NILP (w->vchild))
- delete_all_subwindows (XWINDOW (w->vchild));
-
- mark_window_as_deleted (w);
-
- f->mirror_dirty = 1;
- return Qnil;
- }
-
-
- DEFUN ("next-window", Fnext_window, Snext_window, 0, 4, 0,
- "Return next window after WINDOW in canonical ordering of windows.\n\
- If omitted, WINDOW defaults to the selected window.\n\
- \n\
- Optional second arg MINIBUF t means count the minibuffer window even\n\
- if not active. MINIBUF nil or omitted means count the minibuffer iff\n\
- it is active. MINIBUF neither t nor nil means not to count the\n\
- minibuffer even if it is active.\n\
- \n\
- Several frames may share a single minibuffer; if the minibuffer\n\
- counts, all windows on all frames that share that minibuffer count\n\
- too. Therefore, `next-window' can be used to iterate through the\n\
- set of windows even when the minibuffer is on another frame. If the\n\
- minibuffer does not count, only windows from WINDOW's frame count.\n\
- \n\
- Optional third arg ALL-FRAMES t means include windows on all frames.\n\
- ALL-FRAMES nil or omitted means cycle within the frames as specified\n\
- above. ALL-FRAMES = `visible' means include windows on all visible frames.\n\
- ALL-FRAMES = 0 means include windows on all visible and iconified frames.\n\
- Anything else means restrict to WINDOW's frame.\n\
- \n\
- If you use consistent values for MINIBUF and ALL-FRAMES, you can use\n\
- `next-window' to iterate through the entire cycle of acceptable\n\
- windows, eventually ending up back at the window you started with.\n\
- `previous-window' traverses the same cycle, in the reverse order.")
- (window, minibuf, all_frames, ignored)
- Lisp_Object window, minibuf, all_frames, ignored;
- {
- Lisp_Object tem;
- Lisp_Object start_window;
-
- if (NILP (window))
- window = Fselected_window (Qnil);
- else
- CHECK_LIVE_WINDOW (window, 0);
-
- start_window = window;
-
- /* minibuf == nil may or may not include minibuffers.
- Decide if it does. */
- if (NILP (minibuf))
- minibuf = (minibuf_level ? Qt : Qlambda);
-
- #if 0 /* #### old code, not in FSF. Probably should be deleted. */
- if (EQ (mini, Qt)
- || (! NILP (mini) && minibuf_level))
- {
- if (FRAMEP (Vdefault_minibuffer_frame))
- all_frames = Qt;
- }
- #endif
-
- /* all_frames == nil doesn't specify which frames to include. */
- if (NILP (all_frames))
- all_frames = (EQ (minibuf, Qt)
- ? (FRAME_MINIBUF_WINDOW
- (XFRAME
- (WINDOW_FRAME
- (XWINDOW (window)))))
- : Qnil);
- else if (EQ (all_frames, Qvisible))
- ;
- else if (EQ (all_frames, Qzero))
- ;
- else if (! EQ (all_frames, Qt))
- all_frames = Qnil;
- /* Now all_frames is t meaning search all frames,
- nil meaning search just current frame,
- visible meaning search just visible frames,
- 0 meaning search visible and iconified frames,
- or a window, meaning search the frame that window belongs to. */
-
- /* Do this loop at least once, to get the next window, and perhaps
- again, if we hit the minibuffer and that is not acceptable. */
- do
- {
- /* Find a window that actually has a next one. This loop
- climbs up the tree. */
- while (tem = XWINDOW (window)->next, NILP (tem))
- if (tem = XWINDOW (window)->parent, !NILP (tem))
- window = tem;
- else /* window must be minibuffer window now */
- {
- /* We've reached the end of this frame.
- Which other frames are acceptable? */
- tem = WINDOW_FRAME (XWINDOW (window));
-
- if (! NILP (all_frames))
- {
- Lisp_Object tem1;
-
- tem1 = tem;
- tem = next_frame (tem, all_frames);
- /* In the case where the minibuffer is active,
- and we include its frame as well as the selected one,
- next_frame may get stuck in that frame.
- If that happens, go back to the selected frame
- so we can complete the cycle. */
- if (EQ (tem, tem1))
- XSETFRAME (tem, selected_frame ());
- }
-
- tem = FRAME_ROOT_WINDOW (XFRAME (tem));
- break;
- }
-
- window = tem;
-
- /* If we're in a combination window, find its first child and
- recurse on that. Otherwise, we've found the window we want. */
- while (1)
- {
- if (!NILP (XWINDOW (window)->hchild))
- window = XWINDOW (window)->hchild;
- else if (!NILP (XWINDOW (window)->vchild))
- window = XWINDOW (window)->vchild;
- else break;
- }
- }
- /* Which windows are acceptible?
- Exit the loop and accept this window if
- this isn't a minibuffer window, or
- we're accepting minibuffer windows, or
- we've come all the way around and we're back at the original window. */
- while (MINI_WINDOW_P (XWINDOW (window))
- && ! EQ (minibuf, Qt)
- && ! EQ (window, start_window));
-
- return window;
- }
-
- DEFUN ("previous-window", Fprevious_window, Sprevious_window, 0, 4, 0,
- "Return the window preceeding WINDOW in canonical ordering of windows.\n\
- If omitted, WINDOW defaults to the selected window.\n\
- \n\
- Optional second arg MINIBUF t means count the minibuffer window even\n\
- if not active. MINIBUF nil or omitted means count the minibuffer iff\n\
- it is active. MINIBUF neither t nor nil means not to count the\n\
- minibuffer even if it is active.\n\
- \n\
- Several frames may share a single minibuffer; if the minibuffer\n\
- counts, all windows on all frames that share that minibuffer count\n\
- too. Therefore, `previous-window' can be used to iterate through\n\
- the set of windows even when the minibuffer is on another frame. If\n\
- the minibuffer does not count, only windows from WINDOW's frame count\n\
- \n\
- Optional third arg ALL-FRAMES t means include windows on all frames.\n\
- ALL-FRAMES nil or omitted means cycle within the frames as specified\n\
- above. ALL-FRAMES = `visible' means include windows on all visible frames.\n\
- ALL-FRAMES = 0 means include windows on all visible and iconified frames.\n\
- Anything else means restrict to WINDOW's frame.\n\
- \n\
- If you use consistent values for MINIBUF and ALL-FRAMES, you can use\n\
- `previous-window' to iterate through the entire cycle of acceptable\n\
- windows, eventually ending up back at the window you started with.\n\
- `next-window' traverses the same cycle, in the reverse order.")
- (window, minibuf, all_frames, ignored)
- Lisp_Object window, minibuf, all_frames, ignored;
- {
- Lisp_Object tem;
- Lisp_Object start_window;
-
- if (NILP (window))
- window = Fselected_window (Qnil);
- else
- CHECK_LIVE_WINDOW (window, 0);
-
- start_window = window;
-
- /* minibuf == nil may or may not include minibuffers.
- Decide if it does. */
- if (NILP (minibuf))
- minibuf = (minibuf_level ? Qt : Qlambda);
-
- #if 0 /* #### old code, not in FSF. Probably should be deleted. */
- if (EQ (mini, Qt)
- || (! NILP (mini) && minibuf_level))
- {
- if (FRAMEP (Vdefault_minibuffer_frame))
- all_frames = Qt;
- }
- #endif
-
- /* all_frames == nil doesn't specify which frames to include.
- Decide which frames it includes. */
- if (NILP (all_frames))
- all_frames = (EQ (minibuf, Qt)
- ? (FRAME_MINIBUF_WINDOW
- (XFRAME
- (WINDOW_FRAME
- (XWINDOW (window)))))
- : Qnil);
- else if (EQ (all_frames, Qvisible))
- ;
- else if (EQ (all_frames, Qzero))
- ;
- else if (! EQ (all_frames, Qt))
- all_frames = Qnil;
- /* Now all_frames is t meaning search all frames,
- nil meaning search just current frame,
- visible meaning search just visible frames,
- 0 meaning search visible and iconified frames,
- or a window, meaning search the frame that window belongs to. */
-
- /* Do this loop at least once, to get the next window, and perhaps
- again, if we hit the minibuffer and that is not acceptable. */
- do
- {
- /* Find a window that actually has a next one. This loop
- climbs up the tree. */
- while (tem = XWINDOW (window)->prev, NILP (tem))
- if (tem = XWINDOW (window)->parent, !NILP (tem))
- window = tem;
- else /* window must be minibuffer window now */
- {
- /* We have found the top window on the frame.
- Which frames are acceptable? */
- tem = WINDOW_FRAME (XWINDOW (window));
-
- if (! NILP (all_frames))
- /* It's actually important that we use prev_frame here,
- rather than next_frame. All the windows acceptable
- according to the given parameters should form a ring;
- Fnext_window and Fprevious_window should go back and
- forth around the ring. If we use next_frame here,
- then Fnext_window and Fprevious_window take different
- paths through the set of acceptable windows.
- window_loop assumes that these `ring' requirement are
- met. */
- {
- Lisp_Object tem1;
-
- tem1 = tem;
- tem = prev_frame (tem, all_frames);
- /* In the case where the minibuffer is active,
- and we include its frame as well as the selected one,
- next_frame may get stuck in that frame.
- If that happens, go back to the selected frame
- so we can complete the cycle. */
- if (EQ (tem, tem1))
- XSETFRAME (tem, selected_frame ());
- }
-
- /* If this frame has a minibuffer, find that window first,
- because it is conceptually the last window in that frame. */
- if (FRAME_HAS_MINIBUF_P (XFRAME (tem)))
- tem = FRAME_MINIBUF_WINDOW (XFRAME (tem));
- else
- tem = FRAME_ROOT_WINDOW (XFRAME (tem));
-
- break;
- }
-
- window = tem;
-
- /* If we're in a combination window, find its first child and
- recurse on that. Otherwise, we've found the window we want. */
- while (1)
- {
- if (!NILP (XWINDOW (window)->hchild))
- window = XWINDOW (window)->hchild;
- else if (!NILP (XWINDOW (window)->vchild))
- window = XWINDOW (window)->vchild;
- else break;
- while (tem = XWINDOW (window)->next, !NILP (tem))
- window = tem;
- }
- }
- /* Which windows are acceptible?
- Exit the loop and accept this window if
- this isn't a minibuffer window, or
- we're accepting minibuffer windows, or
- we've come all the way around and we're back at the original window. */
- while (MINI_WINDOW_P (XWINDOW (window))
- && ! EQ (minibuf, Qt)
- && ! EQ (window, start_window));
-
- return window;
- }
-
- DEFUN ("next-vertical-window", Fnext_vertical_window, Snext_vertical_window,
- 0, 1, 0,
- "Return the next window which is vertically after WINDOW.\n")
- (window)
- Lisp_Object window;
- {
- Lisp_Object root;
- struct window *w = decode_window (window);
- XSETWINDOW (window, w);
-
- if (MINI_WINDOW_P (XWINDOW (window)))
- return Qnil;
-
- root = FRAME_ROOT_WINDOW (XFRAME (WINDOW_FRAME (XWINDOW (window))));
-
- if (EQ (window, root))
- {
- while (1)
- if (!NILP (XWINDOW (window)->hchild))
- window = XWINDOW (window)->hchild;
- else if (!NILP (XWINDOW (window)->vchild))
- window = XWINDOW (window)->vchild;
- else
- return window;
- }
-
- do
- {
- if (!NILP (XWINDOW (window)->parent) &&
- !NILP (XWINDOW (XWINDOW (window)->parent)->vchild))
- {
- if (!NILP (XWINDOW (window)->next))
- return XWINDOW (window)->next;
- else
- window = XWINDOW (window)->parent;
- }
- else
- window = XWINDOW (window)->parent;
- }
- while (!EQ (window, root));
-
- while (1)
- if (!NILP (XWINDOW (window)->hchild))
- window = XWINDOW (window)->hchild;
- else if (!NILP (XWINDOW (window)->vchild))
- window = XWINDOW (window)->vchild;
- else
- return window;
- }
-
- DEFUN ("other-window", Fother_window, Sother_window, 1, 3, "p",
- "Select the N'th different window on this frame.\n\
- All windows on current frame are arranged in a cyclic order.\n\
- This command selects the window N steps away in that order.\n\
- A negative N moves in the opposite order.\n\
- \n\
- If optional argument FRAME is `visible', search all visible frames.\n\
- If FRAME is 0, search all visible and iconified frames.\n\
- If FRAME is t, search all frames.\n\
- If FRAME is nil, search only the selected frame.\n\
- If FRAME is a frame, search only that frame.")
- (n, frame, ignored)
- Lisp_Object n, frame, ignored;
- {
- int i;
- Lisp_Object w;
-
- CHECK_INT (n, 0);
- w = Fselected_window (Qnil);
- i = XINT (n);
-
- while (i > 0)
- {
- w = Fnext_window (w, Qnil, frame, Qnil);
- i--;
- }
- while (i < 0)
- {
- w = Fprevious_window (w, Qnil, frame, Qnil);
- i++;
- }
- Fselect_window (w);
- return Qnil;
- }
-
-
- /* Look at all windows, performing an operation specified by TYPE
- with argument OBJ.
-
- If FRAMES is Qt, look at all frames, if Qnil, look at just the selected
- frame. If FRAMES is a frame, just look at windows on that frame.
- If MINI is non-zero, perform the operation on minibuffer windows too.
- */
-
- enum window_loop
- {
- WINDOW_LOOP_UNUSED,
- GET_BUFFER_WINDOW, /* Arg is buffer */
- GET_LRU_WINDOW, /* Arg is t for full-width windows only */
- DELETE_OTHER_WINDOWS, /* Arg is window not to delete */
- DELETE_BUFFER_WINDOWS, /* Arg is buffer */
- GET_LARGEST_WINDOW,
- UNSHOW_BUFFER, /* Arg is buffer */
- GET_BUFFER_WINDOW_COUNT, /* Arg is buffer */
- GET_BUFFER_MRU_WINDOW /* Arg is buffer */
- };
-
- static Lisp_Object
- window_loop (enum window_loop type,
- Lisp_Object obj,
- int mini,
- Lisp_Object frames,
- int dedicated_too)
- {
- /* This function can GC if type == DELETE_BUFFER_WINDOWS or UNSHOW_BUFFER */
- Lisp_Object w;
- Lisp_Object best_window;
- Lisp_Object next_window;
- Lisp_Object last_window;
- struct frame *frame, *sel_frame;
- Lisp_Object frame_arg = Qt;
- int count = 0; /* for GET_BUFFER_WINDOW_COUNT */
- /* #### I think the change of "precomputing" last_window and next_window
- * #### catch the lossage this is meant(?) to punt on...
- */
- int lose_lose = 0;
- Lisp_Object dev;
-
- DEVICE_LOOP (dev)
- {
- if (NILP (DEVICE_SELECTED_FRAME (XDEVICE (XCAR (dev)))))
- continue;
- else
- sel_frame = XFRAME (DEVICE_SELECTED_FRAME (XDEVICE (XCAR (dev))));
-
- /* If we're only looping through windows on a particular frame,
- frame points to that frame. If we're looping through windows
- on all frames, frame is 0. */
- if (FRAMEP (frames))
- frame = XFRAME (frames);
- else if (NILP (frames))
- frame = sel_frame;
- else
- frame = 0;
- if (frame)
- frame_arg = Qlambda;
- else if (EQ (frames, Qzero))
- frame_arg = frames;
- else if (EQ (frames, Qvisible))
- frame_arg = frames;
-
- /* frame_arg is Qlambda to stick to one frame,
- Qvisible to consider all visible frames,
- or Qt otherwise. */
-
- /* Pick a window to start with. */
- if (WINDOWP (obj))
- w = obj;
- else if (frame)
- w = FRAME_SELECTED_WINDOW (frame);
- else
- w = FRAME_SELECTED_WINDOW (sel_frame);
-
- /* Figure out the last window we're going to mess with. Since
- Fnext_window, given the same options, is guaranteed to go in a
- ring, we can just use Fprevious_window to find the last one.
-
- We can't just wait until we hit the first window again,
- because it might be deleted. */
-
- last_window = Fprevious_window (w, mini ? Qt : Qnil, frame_arg, Qnil);
-
- best_window = Qnil;
- for (;;)
- {
- struct window *p = XWINDOW (w);
- struct frame *w_frame = XFRAME (WINDOW_FRAME (p));
-
- /* Pick the next window now, since some operations will delete
- the current window. */
- next_window = Fnext_window (w, mini ? Qt : Qnil, frame_arg, Qnil);
-
- /* #### Still needed ?? */
- /* Given the outstanding quality of the rest of this code,
- I feel no shame about putting this piece of shit in. */
- if (++lose_lose >= 500)
- return Qnil;
-
- /* Note that we do not pay attention here to whether
- the frame is visible, since Fnext_window skips non-visible frames
- if that is desired, under the control of frame_arg. */
- if (! MINI_WINDOW_P (p)
- || (mini && minibuf_level > 0))
- switch (type)
- {
- case GET_BUFFER_WINDOW:
- {
- if (XBUFFER (p->buffer) == XBUFFER (obj))
- return w;
- break;
- }
-
- case GET_BUFFER_WINDOW_COUNT:
- {
- if (XBUFFER (p->buffer) == XBUFFER (obj))
- count++;
- break;
- }
-
- case GET_LRU_WINDOW:
- {
- /* t as arg means consider only full-width windows */
- if (!NILP (obj)
- && window_char_width (p, 0) != FRAME_WIDTH (w_frame))
- break;
- /* Ignore dedicated windows and minibuffers. */
- if (MINI_WINDOW_P (p)
- || (dedicated_too ? 0 : !NILP (p->dedicated)))
- break;
- if (NILP (best_window)
- || (XINT (XWINDOW (best_window)->use_time)
- > XINT (p->use_time)))
- best_window = w;
- break;
- }
-
- case GET_BUFFER_MRU_WINDOW:
- {
- /* #### what about the first check in GET_LRU_WINDOW? */
- /* Ignore dedicated windows and minibuffers. */
- if (MINI_WINDOW_P (p)
- || (dedicated_too ? 0 : !NILP (p->dedicated)))
- break;
-
- if (XBUFFER (p->buffer) == XBUFFER (obj))
- {
- if (NILP (best_window)
- || (XINT (XWINDOW (best_window)->use_time)
- < XINT (p->use_time)))
- best_window = w;
- }
- break;
- }
-
- case DELETE_OTHER_WINDOWS:
- {
- /* Don't delete the last window on a frame; this can
- happen when the minibuffer is selected, and would
- cause the frame to be deleted. */
- if (p != XWINDOW (obj) && !TOP_LEVEL_WINDOW_P (XWINDOW (w)))
- Fdelete_window (w);
- break;
- }
-
- case DELETE_BUFFER_WINDOWS:
- {
- if (EQ (p->buffer, obj))
- {
- /* If we're deleting the buffer displayed in the
- only window on the frame, find a new buffer
- to display there. */
- if (NILP (p->parent))
- {
- Lisp_Object new_buffer =
- Fother_buffer (obj, Qnil, Qnil);
- if (NILP (new_buffer))
- new_buffer =
- Fget_buffer_create (QSscratch);
- Fset_window_buffer (w, new_buffer);
- if (EQ (w, Fselected_window (Qnil)))
- Fset_buffer (p->buffer);
- }
- else
- Fdelete_window (w);
- }
- break;
- }
-
- case GET_LARGEST_WINDOW:
- {
- /* Ignore dedicated windows and minibuffers. */
- if (MINI_WINDOW_P (p)
- || (dedicated_too ? 0 : !NILP (p->dedicated)))
- break;
- {
- /* write the check as follows to avoid tripping
- error_check_window() --ben */
- struct window *b = NILP (best_window) ? 0 :
- XWINDOW (best_window);
- if (NILP (best_window)
- || ((WINDOW_HEIGHT (p) * WINDOW_WIDTH (p))
- > (WINDOW_HEIGHT (b) * WINDOW_WIDTH (b))))
- best_window = w;
- }
- break;
- }
-
- case UNSHOW_BUFFER:
- {
- if (EQ (p->buffer, obj))
- {
- /* Find another buffer to show in this window. */
- Lisp_Object another_buffer =
- Fother_buffer (obj, Qnil, Qnil);
- if (NILP (another_buffer))
- another_buffer
- = Fget_buffer_create (QSscratch);
- /* If this window is dedicated, and in a frame
- of its own, kill the frame. */
- if (EQ (w, FRAME_ROOT_WINDOW (w_frame))
- && !NILP (p->dedicated)
- && other_visible_frames (w_frame))
- {
- /* Skip the other windows on this frame.
- There might be one, the minibuffer! */
- if (! EQ (w, last_window))
- while (w_frame == XFRAME (WINDOW_FRAME
- (XWINDOW (next_window))))
- {
- /* As we go, check for the end of the
- loop. We mustn't start going
- around a second time. */
- if (EQ (next_window, last_window))
- {
- last_window = w;
- break;
- }
- next_window = Fnext_window (next_window,
- mini ? Qt : Qnil,
- frame_arg, Qnil);
- }
- /* Now we can safely delete the frame. */
- delete_frame_internal (WINDOW_FRAME (p), 0);
- }
- else
- {
- /* Otherwise show a different buffer in the
- window. */
- p->dedicated = Qnil;
- Fset_window_buffer (w, another_buffer);
- if (EQ (w, Fselected_window (Qnil)))
- Fset_buffer (p->buffer);
- }
- }
- break;
- }
-
- default:
- abort ();
- }
-
- if (EQ (w, last_window))
- break;
-
- w = next_window;
- }
- }
-
- if (type == GET_BUFFER_WINDOW_COUNT)
- return (make_number (count));
- else
- return (best_window);
- }
-
- /* only display_glyph_in_buffer in xdisp.c is using this at the moment */
- int
- buffer_window_count (struct buffer *b, struct frame *f)
- {
- Lisp_Object buffer, frame;
-
- XSETFRAME (frame, f);
- XSETBUFFER (buffer, b);
-
- return XINT (window_loop (GET_BUFFER_WINDOW_COUNT, buffer, 0, frame, 1));
- }
-
- /* only display_glyph_in_buffer in xdisp.c is using this at the moment */
- int
- buffer_window_mru (struct window *w)
- {
- Lisp_Object window =
- window_loop (GET_BUFFER_MRU_WINDOW, w->buffer, 0, w->frame, 1);
-
- if (NILP (window))
- return 0;
- else if (XWINDOW (window) == w)
- return 1;
- else
- return 0;
- }
-
-
- DEFUN ("get-lru-window", Fget_lru_window, Sget_lru_window, 0, 1, 0,
- "Return the window least recently selected or used for display.\n\
- If optional argument FRAME is `visible', search all visible frames.\n\
- If FRAME is 0, search all visible and iconified frames.\n\
- If FRAME is t, search all frames.\n\
- If FRAME is nil, search only the selected frame.\n\
- If FRAME is a frame, search only that frame.")
- (frame)
- Lisp_Object frame;
- {
- Lisp_Object w;
- /* First try for a non-dedicated window that is full-width */
- w = window_loop (GET_LRU_WINDOW, Qt, 0, frame, 0);
- if (!NILP (w) && !EQ (w, Fselected_window (Qnil)))
- return w;
-
- /* Then try for any non-dedicated window */
- w = window_loop (GET_LRU_WINDOW, Qnil, 0, frame, 0);
- if (!NILP (w) && !EQ (w, Fselected_window (Qnil)))
- return w;
-
- /* then try for a dedicated window that is full-width */
- w = window_loop (GET_LRU_WINDOW, Qt, 0, frame, 1);
- if (!NILP (w) && !EQ (w, Fselected_window (Qnil)))
- return w;
-
- /* If none of them, then all windows, dedicated or not. */
- w = window_loop (GET_LRU_WINDOW, Qnil, 0, frame, 1);
-
- /* At this point we damn well better have found something. */
- if (NILP (w)) abort ();
-
- return (w);
- }
-
- DEFUN ("get-largest-window", Fget_largest_window, Sget_largest_window, 0, 1, 0,
- "Return the window largest in area.\n\
- If optional argument FRAME is `visible', search all visible frames.\n\
- If FRAME is 0, search all visible and iconified frames.\n\
- If FRAME is t, search all frames.\n\
- If FRAME is nil, search only the selected frame.\n\
- If FRAME is a frame, search only that frame.")
- (frame)
- Lisp_Object frame;
- {
- /* Search dedicated windows too (is this sensible?) */
- return window_loop (GET_LARGEST_WINDOW, Qnil, 0, frame, 1);
- }
-
- DEFUN ("get-buffer-window", Fget_buffer_window, Sget_buffer_window, 1, 3, 0,
- "Return a window currently displaying BUFFER, or nil if none.\n\
- If optional argument FRAME is `visible', search all visible frames.\n\
- If optional argument FRAME is 0, search all visible and iconified frames.\n\
- If FRAME is t, search all frames.\n\
- If FRAME is nil, search only the selected frame.\n\
- If FRAME is a frame, search only that frame.")
- (buffer, frame, ignored)
- Lisp_Object buffer, frame, ignored;
- {
- buffer = Fget_buffer (buffer);
- if (BUFFERP (buffer))
- /* Search dedicated windows too. */
- return window_loop (GET_BUFFER_WINDOW, buffer, 1, frame, 1);
- else
- return Qnil;
- }
-
- /* These functions used to be `buffer-left-margin-pixel-width', etc.
- but there is no sensible way to implement those functions, since
- you can't in general derive a window from a buffer. */
-
- DEFUN ("window-left-margin-pixel-width", Fwindow_left_margin_pixel_width,
- Swindow_left_margin_pixel_width, 0, 1, 0,
- "Return the width in pixels of the left outside margin of window WINDOW.\n\
- If WINDOW is nil, the selected window is assumed.")
- (window)
- Lisp_Object window;
- {
- struct window *w = decode_window (window);
-
- return (make_number (window_left_margin_width (w)));
- }
-
- DEFUN ("window-right-margin-pixel-width", Fwindow_right_margin_pixel_width,
- Swindow_right_margin_pixel_width, 0, 1, 0,
- "Return the width in pixels of the right outside margin of window WINDOW.\n\
- If WINDOW is nil, the selected window is assumed.")
- (window)
- Lisp_Object window;
- {
- struct window *w = decode_window (window);
-
- return (make_number (window_right_margin_width (w)));
- }
-
- DEFUN ("delete-other-windows", Fdelete_other_windows, Sdelete_other_windows,
- 0, 1, "",
- "Make WINDOW (or the selected window) fill its frame.\n\
- Only the frame WINDOW is on is affected.\n\
- This function tries to reduce display jumps\n\
- by keeping the text previously visible in WINDOW\n\
- in the same place on the frame. Doing this depends on\n\
- the value of (window-start WINDOW), so if calling this function\n\
- in a program gives strange scrolling, make sure the window-start\n\
- value is reasonable when this function is called.")
- (window)
- Lisp_Object window;
- {
- struct window *w = decode_window (window);
- struct buffer *b = XBUFFER (w->buffer);
- Bufpos start_pos;
- int old_top = WINDOW_TOP (w);
-
- XSETWINDOW (window, w);
-
- /* Ignore dedicated windows. */
- window_loop (DELETE_OTHER_WINDOWS, window, 0, w->frame, 0);
-
- start_pos = marker_position (w->start[CURRENT_DISP]);
-
- /* Try to minimize scrolling, by setting the window start to the
- point which will cause the text at the old window start to be at
- the same place on the frame. But don't try to do this if the
- window start is outside the visible portion (as might happen when
- the display is not current, due to typeahead). */
- if (start_pos >= BUF_BEGV (b) && start_pos <= BUF_ZV (b)
- && !MINI_WINDOW_P (w))
- {
- Bufpos new_start = start_with_line_at_pixpos (w, start_pos, old_top);
-
- if (new_start >= BUF_BEGV (b) && new_start <= BUF_ZV (b))
- {
- Fset_marker (w->start[CURRENT_DISP], make_number (new_start),
- w->buffer);
- w->start_at_line_beg = !NILP (Fbolp (w->buffer));
- }
- }
-
- return Qnil;
- }
-
- DEFUN ("delete-windows-on", Fdelete_windows_on, Sdelete_windows_on,
- 1, 2, "bDelete windows on (buffer): ",
- "Delete all windows showing BUFFER.\n\
- Optional second argument FRAME controls which frames are affected.\n\
- If nil or omitted, delete all windows showing BUFFER in any frame.\n\
- If t, delete only windows showing BUFFER in the selected frame.\n\
- If `visible', delete all windows showing BUFFER in any visible frame.\n\
- If a frame, delete only windows showing BUFFER in that frame.")
- (buffer, frame)
- Lisp_Object buffer, frame;
- {
- /* This function can GC */
- /* FRAME uses t and nil to mean the opposite of what window_loop
- expects. */
- if (!FRAMEP (frame))
- frame = NILP (frame) ? Qt : Qnil;
-
- if (!NILP (buffer))
- {
- buffer = Fget_buffer (buffer);
- CHECK_BUFFER (buffer, 0);
- /* Ignore dedicated windows. */
- window_loop (DELETE_BUFFER_WINDOWS, buffer, 0, frame, 0);
- }
- return Qnil;
- }
-
- DEFUN ("replace-buffer-in-windows", Freplace_buffer_in_windows,
- Sreplace_buffer_in_windows,
- 1, 1, "bReplace buffer in windows: ",
- "Replace BUFFER with some other buffer in all windows showing it.")
- (buffer)
- Lisp_Object buffer;
- {
- /* This function can GC */
- if (!NILP (buffer))
- {
- buffer = Fget_buffer (buffer);
- CHECK_BUFFER (buffer, 0);
- /* Ignore dedicated windows. */
- window_loop (UNSHOW_BUFFER, buffer, 0, Qt, 0);
- }
- return Qnil;
- }
-
- /* The smallest acceptable dimensions for a window. Anything smaller
- might crash Emacs. */
- #define MIN_SAFE_WINDOW_WIDTH (2)
- #define MIN_SAFE_WINDOW_HEIGHT (2)
-
- /* Make sure that window_min_height and window_min_width are
- not too small; if they are, set them to safe minima. */
-
- static void
- check_min_window_sizes (void)
- {
- /* Smaller values might permit a crash. */
- if (window_min_width < MIN_SAFE_WINDOW_WIDTH)
- window_min_width = MIN_SAFE_WINDOW_WIDTH;
- if (window_min_height < MIN_SAFE_WINDOW_HEIGHT)
- window_min_height = MIN_SAFE_WINDOW_HEIGHT;
- }
-
- /* If *ROWS or *COLS are too small a size for FRAME, set them to the
- minimum allowable size. */
- void
- check_frame_size (struct frame *frame, int *rows, int *cols)
- {
- /* For height, we have to see whether the frame has a minibuffer, and
- whether it wants a modeline. */
- int min_height = ((FRAME_MINIBUF_ONLY_P (frame)
- || ! FRAME_HAS_MINIBUF_P (frame))
- ? MIN_SAFE_WINDOW_HEIGHT
- : 2 * MIN_SAFE_WINDOW_HEIGHT - 1);
-
- if (*rows < min_height)
- *rows = min_height;
- if (*cols < MIN_SAFE_WINDOW_WIDTH)
- *cols = MIN_SAFE_WINDOW_WIDTH;
- }
-
- /* Normally the window is deleted if it gets too small.
- nodelete nonzero means do not do this.
- (The caller should check later and do so if appropriate) */
- static void
- set_window_pixsize (Lisp_Object window, int new_pixsize, int nodelete,
- int set_height)
- {
- struct window *w = XWINDOW (window);
- struct frame *f = XFRAME (w->frame);
- struct window *c;
- int old_pixsize = (set_height ? WINDOW_HEIGHT (w) : WINDOW_WIDTH (w));
- Lisp_Object child, minor_kid, major_kid;
- int minsize;
- int line_size;
- int defheight, defwidth;
-
- /* #### This is very likely incorrect and instead the char_to_pixel_
- functions should be called. */
- default_face_height_and_width (window, &defheight, &defwidth);
- line_size = (set_height ? defheight : defwidth);
-
- minsize = (set_height ? window_min_height : window_min_width);
- minsize *= line_size;
-
- check_min_window_sizes ();
-
- if (!nodelete
- && !TOP_LEVEL_WINDOW_P (w)
- && new_pixsize < minsize)
- {
- Fdelete_window (window);
- return;
- }
-
- SET_LAST_MODIFIED (w, 0);
- SET_LAST_FACECHANGE (w);
- MARK_FRAME_WINDOWS_STRUCTURE_CHANGED (f); /* multiple windows affected */
- if (set_height)
- {
- WINDOW_HEIGHT (w) = new_pixsize;
- major_kid = w->vchild;
- minor_kid = w->hchild;
- }
- else
- {
- WINDOW_WIDTH (w) = new_pixsize;
- major_kid = w->hchild;
- minor_kid = w->vchild;
- }
-
- if (!NILP (minor_kid))
- {
- for (child = minor_kid; !NILP (child); child = XWINDOW (child)->next)
- {
- if (set_height)
- WINDOW_TOP (XWINDOW (child)) = WINDOW_TOP (w);
- else
- WINDOW_LEFT (XWINDOW (child)) = WINDOW_LEFT (w);
-
- set_window_pixsize (child, new_pixsize, nodelete, set_height);
- }
- }
- else if (!NILP (major_kid))
- {
- int last_pos, last_old_pos, pos, old_pos, first;
- int pixel_adj_left = new_pixsize - old_pixsize;
- int div_val = old_pixsize << 1;
-
- /* Sometimes we may get called with our old size. In that case
- we don't need to do anything. */
- if (!pixel_adj_left)
- return;
-
- last_pos = first = (set_height ? WINDOW_TOP (w) : WINDOW_LEFT (w));
- last_old_pos = 0;
-
- for (child = major_kid; !NILP (child); child = c->next)
- {
- c = XWINDOW (child);
-
- if (set_height)
- {
- old_pos = last_old_pos + WINDOW_HEIGHT (c);
- WINDOW_TOP (c) = last_pos;
- }
- else
- {
- old_pos = last_old_pos + WINDOW_WIDTH (c);
- WINDOW_LEFT (c) = last_pos;
- }
-
- pos = (((old_pos * new_pixsize) << 1) + old_pixsize) / div_val;
- /* All but the the last window should have a height which is
- a multiple of the default line height. */
- if (!NILP (c->next))
- pos = (pos / line_size) * line_size;
-
- /* Avoid confusion: don't delete child if it becomes too small */
- set_window_pixsize (child, pos + first - last_pos, 1, set_height);
-
- last_pos = pos + first;
- last_old_pos = old_pos;
- }
-
- /* Now delete any children that became too small. */
- if (!nodelete)
- for (child = major_kid; !NILP (child); child = XWINDOW (child)->next)
- {
- if (set_height)
- set_window_pixheight (child, WINDOW_HEIGHT (XWINDOW (child)), 0);
- else
- set_window_pixwidth (child, WINDOW_WIDTH (XWINDOW (child)), 0);
- }
- }
- }
-
- /* Set the height of WINDOW and all its inferiors. */
- void
- set_window_pixheight (Lisp_Object window, int new_pixheight, int nodelete)
- {
- set_window_pixsize (window, new_pixheight, nodelete, 1);
- }
-
- /* Recursively set width of WINDOW and its inferiors. */
- void
- set_window_pixwidth (Lisp_Object window, int new_pixwidth, int nodelete)
- {
- set_window_pixsize (window, new_pixwidth, nodelete, 0);
- }
-
-
- static int window_select_count;
-
- DEFUN ("set-window-buffer", Fset_window_buffer, Sset_window_buffer, 2, 2, 0,
- "Make WINDOW display BUFFER as its contents.\n\
- BUFFER can be a buffer or buffer name.")
- (window, buffer)
- Lisp_Object window, buffer;
- {
- Lisp_Object tem;
- struct window *w = decode_window (window);
-
- buffer = Fget_buffer (buffer);
- CHECK_BUFFER (buffer, 1);
-
- if (!BUFFER_LIVE_P (XBUFFER (buffer)))
- error ("Attempt to display deleted buffer");
-
- tem = w->buffer;
- if (NILP (tem))
- error ("Window is deleted");
-
- /* While this seems like a logical thing to do, it causes problems
- because of saved window configurations. It is possible for a
- buffer to get restored into a window in which it is already being
- displayed, but start and point are actually at completely
- different locations. So we let this function complete fully and
- it will then make sure redisplay correctly updates things. */
- #if 0
- else if (EQ (tem, buffer))
- return (Qnil);
- #endif
- else if (! EQ (tem, Qt)) /* w->buffer is t when the window
- is first being set up. */
- {
- if (!NILP (w->dedicated) && !EQ (tem, buffer))
- error ("Window is dedicated to buffer %s",
- string_data (XSTRING (XBUFFER (tem)->name)));
-
- unshow_buffer (w);
- }
-
- w->buffer = buffer;
- w->window_end_pos[CURRENT_DISP] = 0;
- w->hscroll = 0;;
- Fset_marker (w->pointm[CURRENT_DISP],
- make_number (BUF_PT (XBUFFER (buffer))),
- buffer);
- set_marker_restricted (w->start[CURRENT_DISP],
- make_number (XBUFFER (buffer)->last_window_start),
- buffer);
- Fset_marker (w->sb_point, w->start[CURRENT_DISP], buffer);
- w->start_at_line_beg = 0;
- w->force_start = 0; /* Lucid fix */
- SET_LAST_MODIFIED (w, 1);
- SET_LAST_FACECHANGE (w);
- MARK_WINDOWS_CHANGED (w);
- recompute_all_cached_specifiers_in_window (w);
- if (EQ (window, Fselected_window (Qnil)))
- {
- Fset_buffer (buffer);
- #ifdef ENERGIZE
- energize_buffer_shown_hook (w);
- #endif
- }
- return Qnil;
- }
-
- DEFUN ("select-window", Fselect_window, Sselect_window, 1, 1, 0,
- "Select WINDOW. Most editing will apply to WINDOW's buffer.\n\
- The main editor command loop selects the buffer of the selected window\n\
- before each command.")
- (window)
- Lisp_Object window;
- {
- struct window *w;
- Lisp_Object old_selected_window = Fselected_window (Qnil);
-
- CHECK_LIVE_WINDOW (window, 0);
- w = XWINDOW (window);
-
- /* we have already caught dead-window errors */
- if (!NILP (w->hchild) || !NILP (w->vchild))
- error ("Trying to select non-leaf window");
-
- w->use_time = make_number (++window_select_count);
- if (EQ (window, old_selected_window))
- return window;
-
- /* deselect the old window, if it exists (it might not exist if
- the selected device has no frames, which occurs at startup) */
- if (!NILP (old_selected_window))
- {
- struct window *ow = XWINDOW (old_selected_window);
-
- #ifdef ENERGIZE
- if (! MINI_WINDOW_P (w))
- energize_window_deselected_hook (ow);
- #endif
-
- Fset_marker (ow->pointm[CURRENT_DISP],
- make_number (BUF_PT (XBUFFER (ow->buffer))),
- ow->buffer);
-
- MARK_WINDOWS_CHANGED (ow);
- }
-
- /* now select the window's frame */
- FRAME_SELECTED_WINDOW (XFRAME (WINDOW_FRAME (w))) = window;
- select_frame_1 (WINDOW_FRAME (w));
-
- /* also select the window's buffer */
- record_buffer (w->buffer);
- Fset_buffer (w->buffer);
-
- /* Go to the point recorded in the window.
- This is important when the buffer is in more
- than one window. It also matters when
- redisplay_window has altered point after scrolling,
- because it makes the change only in the window. */
- {
- Bufpos new_point = marker_position (w->pointm[CURRENT_DISP]);
- if (new_point < BUF_BEGV (current_buffer))
- new_point = BUF_BEGV (current_buffer);
- else if (new_point > BUF_ZV (current_buffer))
- new_point = BUF_ZV (current_buffer);
-
- BUF_SET_PT (current_buffer, new_point);
- }
-
- MARK_WINDOWS_CHANGED (w);
-
- #ifdef ENERGIZE
- if (! MINI_WINDOW_P (w))
- energize_window_selected_hook (w);
- #endif
-
- return window;
- }
-
- /* #### This function is not synched up with FSF 19.28. There's lots
- of added junk (`special-display-buffer-names' etc.) that I haven't looked
- into to determine whether it's crockish or not, so I'm leaving this
- alone. --ben */
-
- DEFUN ("display-buffer", Fdisplay_buffer, Sdisplay_buffer, 1, 3,
- "BDisplay buffer:\nP",
- "Make BUFFER appear in some window on the current frame, but don't\n\
- select it.\n\
- BUFFER can be a buffer or a buffer name.\n\
- If BUFFER is shown already in some window in the current frame,\n\
- just uses that one, unless the window is the selected window and\n\
- NOT-THIS-WINDOW-P is non-nil (interactively, with prefix arg).\n\
- \n\
- If BUFFER has a dedicated frame, display on that frame instead of\n\
- the current frame, unless OVERRIDE-FRAME is non-nil.\n\
- \n\
- If OVERRIDE-FRAME is non-nil, display on that frame instead of\n\
- the current frame (or the dedicated frame).\n\
- \n\
- If `pop-up-windows' is non-nil, always use the\n\
- current frame and create a new window regardless of whether the\n\
- buffer has a dedicated frame, and regardless of whether\n\
- OVERRIDE-FRAME was specified.\n\
- \n\
- Returns the window displaying BUFFER.")
- (buffer, not_this_window_p, override_frame)
- Lisp_Object buffer, not_this_window_p, override_frame;
- {
- /* This function can GC */
- Lisp_Object window;
- Lisp_Object old_frame, target_frame;
-
- old_frame = Fselected_frame (Qnil);
-
- buffer = Fget_buffer (buffer);
- CHECK_BUFFER (buffer, 0);
-
- target_frame = old_frame;
-
- if (!NILP (Vpre_display_buffer_function))
- {
- struct gcpro gcpro1, gcpro2, gcpro3;
- /* No need to gcpro target_frame, since GC doesn't relocate */
- GCPRO3 (buffer, not_this_window_p, override_frame);
- call3 (Vpre_display_buffer_function,
- buffer, not_this_window_p, override_frame);
- UNGCPRO;
- /* this hook may have selected some other frame, so take notice. */
- target_frame = Fselected_frame (Qnil);
- }
-
- /* Give the user the ability to completely reimplement this function in
- lisp via the `display-buffer-function'.
- */
- if (!NILP (Vdisplay_buffer_function))
- {
- struct gcpro gcpro1, gcpro2, gcpro3;
- GCPRO3 (buffer, not_this_window_p, override_frame);
- RETURN_UNGCPRO (call3 (Vdisplay_buffer_function,
- buffer, not_this_window_p,
- override_frame));
- }
-
- /* If the buffer has a dedicated frame, that takes precedence over the
- current frame, and over what the pre-display-buffer-function did.
- */
- if (!NILP (XBUFFER (buffer)->dedicated_frame) &&
- FRAME_LIVE_P (XFRAME (XBUFFER (buffer)->dedicated_frame))) /* XEmacs */
- target_frame = XBUFFER (buffer)->dedicated_frame;
-
- /* if override_frame is supplied, that takes precedence over everything.
- (This is gonna look bad if the pre-display-buffer-function raised
- some other frame already.)
- */
- if (!NILP (override_frame))
- target_frame = override_frame;
-
- CHECK_LIVE_FRAME (target_frame, 0);
-
- /* If we have switched frames, then set not_this_window_p to false.
- Switching frames means that selected_window is no longer the same
- as it was on entry -- it's the selected_window of target_frame
- instead of old_frame, so it's a fine candidate for display. */
- if (!EQ (old_frame, target_frame))
- not_this_window_p = Qnil;
-
- /* if it's in the selected window, and that's ok, then we're done. */
- if (NILP (not_this_window_p)
- && XBUFFER (XWINDOW (Fselected_window (Qnil))->buffer) == XBUFFER (buffer))
- return Fselected_window (Qnil);
-
- /* Otherwise, find some window that it's already in, and return that,
- unless that window is the selected window and that isn't ok.
- What a contorted mess! */
- window = Fget_buffer_window (buffer, target_frame, Qnil);
- if (!NILP (window)
- && (NILP (not_this_window_p) || !EQ (window, Fselected_window (Qnil))))
- return window;
-
- #if 0
- /* If there are no frames open that have more than a minibuffer,
- we need to create a new frame. */
- if (pop_up_frames || last_nonminibuf_frame == 0)
- {
- window
- = Fframe_selected_window (call0 (Vpop_up_frame_function));
- Fset_window_buffer (window, buffer);
- # if 0
- Fselect_frame (XWINDOW (window)->frame, Qnil);
- # endif
- return window;
- }
- #endif
-
- /* Otherwise, make it be in some window, splitting if appropriate/possible.
- Do not split a window if we are displaying the buffer in a different
- frame than that which was current when we were called. (It is already
- in a different window by virtue of being in another frame.)
- */
- if ((pop_up_windows
- && EQ (target_frame, old_frame))
- || FRAME_MINIBUF_ONLY_P (selected_frame ()))
- {
- #if 0
- if (FRAME_MINIBUF_ONLY_P (selected_frame ()))
- XSETFRAME (target_frame, last_nonminibuf_frame);
- #endif
- /* Don't try to create a window if would get an error */
- if (split_height_threshold < window_min_height << 1)
- split_height_threshold = window_min_height << 1;
-
- /* Don't try to create a window if would get an error */
- if (split_width_threshold < window_min_width << 1)
- split_width_threshold = window_min_width << 1;
-
- window = Fget_largest_window (target_frame);
-
- if (!NILP (window)
- && window_char_height (XWINDOW (window), 1) >= split_height_threshold
- && (window_char_width (XWINDOW (window), 0) >= split_width_threshold
- ||
- (window_char_width (XWINDOW (window), 0)
- == FRAME_WIDTH (XFRAME (WINDOW_FRAME (XWINDOW (window)))))))
- window = Fsplit_window (window, Qnil, Qnil);
- else
- {
- window = Fget_lru_window (target_frame);
- if ((EQ (window, Fselected_window (Qnil))
- || EQ (XWINDOW (window)->parent, Qnil))
- && window_char_height (XWINDOW (window), 1)
- >= (window_min_height << 1))
- window = Fsplit_window (window, Qnil, Qnil);
- }
- }
- else
- window = Fget_lru_window (target_frame);
-
- /* Bring the window's previous buffer to the top of the MRU chain. */
- if (!NILP (XWINDOW (window)->buffer))
- record_buffer (XWINDOW (window)->buffer);
-
- Fset_window_buffer (window, buffer);
- return window;
- }
-
- void
- temp_output_buffer_show (Lisp_Object buf, Lisp_Object same_frame)
- {
- /* This function can GC */
- Lisp_Object window;
- struct window *w;
- struct buffer *b = XBUFFER (buf);
-
- XBUFFER (buf)->save_modified = BUF_MODIFF (b);
- widen_buffer (b, 0);
- BUF_SET_PT (b, BUF_BEG (b));
-
- if (!EQ (Vtemp_buffer_show_function, Qnil))
- call1 (Vtemp_buffer_show_function, buf);
- else
- {
- window = Fdisplay_buffer (buf, Qnil, same_frame);
-
- if (!EQ (XWINDOW (window)->frame, Fselected_frame (Qnil)))
- Fmake_frame_visible (WINDOW_FRAME (XWINDOW (window)));
-
- Vminibuf_scroll_window = window;
- w = XWINDOW (window);
- w->hscroll = 0;
- set_marker_restricted (w->start[CURRENT_DISP], make_number (1), buf);
- set_marker_restricted (w->pointm[CURRENT_DISP], make_number (1), buf);
- set_marker_restricted (w->sb_point, make_number (1), buf);
- }
- }
-
- static void
- make_dummy_parent (Lisp_Object window)
- {
- Lisp_Object new = Qnil;
- struct window *o = XWINDOW (window);
- struct window *p = alloc_lcrecord (sizeof (struct window),
- lrecord_window);
- struct lcrecord_header preserve_me;
- int uid;
-
- XSETWINDOW (new, p);
- preserve_me = p->header;
- uid = p->header.uid;
- memcpy (p, o, sizeof (struct window));
- p->header = preserve_me;
- p->header.uid = uid;
-
- /* Don't copy the pointers to the line start cache or the face
- instances. */
- p->line_start_cache = Dynarr_new (struct line_start_cache);
- p->face_cache_elements = Dynarr_new (struct face_cache_element);
- p->glyph_cache_elements = Dynarr_new (struct glyph_cache_element);
-
- /* Put new into window structure in place of window */
- replace_window (window, new);
-
- o->next = Qnil;
- o->prev = Qnil;
- o->vchild = Qnil;
- o->hchild = Qnil;
- o->parent = new;
-
- p->start[CURRENT_DISP] = Qnil;
- p->start[DESIRED_DISP] = Qnil;
- p->start[CMOTION_DISP] = Qnil;
- p->pointm[CURRENT_DISP] = Qnil;
- p->pointm[DESIRED_DISP] = Qnil;
- p->pointm[CMOTION_DISP] = Qnil;
- p->sb_point = Qnil;
- p->buffer = Qnil;
- }
-
- DEFUN ("split-window", Fsplit_window, Ssplit_window, 0, 3, "",
- "Split WINDOW, putting SIZE lines in the first of the pair.\n\
- WINDOW defaults to selected one and SIZE to half its size.\n\
- If optional third arg HOR-FLAG is non-nil, split side by side\n\
- and put SIZE columns in the first of the pair.")
- (window, chsize, horflag)
- Lisp_Object window, chsize, horflag;
- {
- Lisp_Object new;
- struct window *o, *p;
- struct frame *f;
- int size;
- int psize;
-
- if (NILP (window))
- window = Fselected_window (Qnil);
- else
- CHECK_WINDOW (window, 0);
-
- o = XWINDOW (window);
- f = XFRAME (WINDOW_FRAME (o));
-
- if (NILP (chsize))
- {
- if (!NILP (horflag))
- /* In the new scheme, we are symmetric with respect to separators
- so there is no need to do weird things here. */
- {
- psize = WINDOW_WIDTH (o) >> 1;
- size = window_pixel_width_to_char_width (o, psize, 0);
- }
- else
- {
- psize = WINDOW_HEIGHT (o) >> 1;
- size = window_pixel_height_to_char_height (o, psize, 1);
- }
- }
- else
- {
- CHECK_INT (chsize, 1);
- size = XINT (chsize);
- if (!NILP (horflag))
- psize = window_char_width_to_pixel_width (o, size, 0);
- else
- psize = window_char_height_to_pixel_height (o, size, 1);
- }
-
- if (MINI_WINDOW_P (o))
- error ("Attempt to split minibuffer window");
- else if (FRAME_NO_SPLIT_P (XFRAME (WINDOW_FRAME (o))))
- error ("Attempt to split unsplittable frame");
-
- check_min_window_sizes ();
-
- if (NILP (horflag))
- {
- if (size < window_min_height
- || size + window_min_height > window_char_height (o, 1))
- /* args_out_of_range_3 (window, chsize, horflag); */
- error ("Window is not tall enough to split");
- if (NILP (o->parent)
- || NILP (XWINDOW (o->parent)->vchild))
- {
- make_dummy_parent (window);
- reset_face_cache_elements (XWINDOW (window));
- new = o->parent;
- XWINDOW (new)->vchild = window;
- XFRAME (o->frame)->mirror_dirty = 1;
- }
- }
- else
- {
- if (size < window_min_width
- || size + window_min_width > window_char_width (o, 0))
- /* args_out_of_range_3 (window, chsize, horflag); */
- error ("Window is not wide enough to split");
- if (NILP (o->parent)
- || NILP (XWINDOW (o->parent)->hchild))
- {
- make_dummy_parent (window);
- reset_face_cache_elements (XWINDOW (window));
- new = o->parent;
- XWINDOW (new)->hchild = window;
- XFRAME (o->frame)->mirror_dirty = 1;
- }
- }
-
- /* Now we know that window's parent is a vertical combination
- if we are dividing vertically, or a horizontal combination
- if we are making side-by-side windows */
-
- MARK_FRAME_WINDOWS_STRUCTURE_CHANGED (f);
- new = allocate_window ();
- p = XWINDOW (new);
-
- p->frame = o->frame;
- p->next = o->next;
- if (!NILP (p->next))
- XWINDOW (p->next)->prev = new;
- p->prev = window;
- o->next = new;
- p->parent = o->parent;
- p->buffer = Qt;
-
- reset_face_cache_elements (p);
- reset_glyph_cache_elements (p);
- Fset_window_buffer (new, o->buffer);
-
-
- /* Apportion the available frame space among the two new windows */
-
- if (!NILP (horflag))
- {
- WINDOW_HEIGHT (p) = WINDOW_HEIGHT (o);
- WINDOW_TOP (p) = WINDOW_TOP (o);
- WINDOW_WIDTH (p) = WINDOW_WIDTH (o) - psize;
- WINDOW_WIDTH (o) = psize;
- WINDOW_LEFT (p) = WINDOW_LEFT (o) + psize;
- }
- else
- {
- WINDOW_LEFT (p) = WINDOW_LEFT (o);
- WINDOW_WIDTH (p) = WINDOW_WIDTH (o);
- WINDOW_HEIGHT (p) = WINDOW_HEIGHT (o) - psize;
- WINDOW_HEIGHT (o) = psize;
- WINDOW_TOP (p) = WINDOW_TOP (o) + psize;
- }
-
- XFRAME (p->frame)->mirror_dirty = 1;
- return new;
- }
-
- static void change_window_height (int delta, int widthflag);
-
- DEFUN ("enlarge-window", Fenlarge_window, Senlarge_window, 1, 2, "_p",
- "Make current window ARG lines bigger.\n\
- From program, optional second arg non-nil means grow sideways ARG columns.")
- (n, side)
- Lisp_Object n, side;
- {
- CHECK_INT (n, 0);
- change_window_height (XINT (n), !NILP (side));
- return Qnil;
- }
-
- DEFUN ("shrink-window", Fshrink_window, Sshrink_window, 1, 2, "_p",
- "Make current window ARG lines smaller.\n\
- From program, optional second arg non-nil means shrink sideways ARG columns.")
- (n, side)
- Lisp_Object n, side;
- {
- CHECK_INT (n, 0);
- change_window_height (-XINT (n), !NILP (side));
- return Qnil;
- }
-
- static int
- window_pixel_height (Lisp_Object window)
- {
- struct window *w = XWINDOW (window);
- return WINDOW_HEIGHT (w);
- }
-
- static int
- window_pixel_height_to_char_height (struct window *w, int pixel_height,
- int include_modeline_p)
- {
- int avail_height;
- int defheight, defwidth;
- int char_height;
- Lisp_Object window;
-
- XSETWINDOW (window, w);
-
- avail_height = (pixel_height -
- window_top_gutter_height (w) -
- window_bottom_gutter_height (w) +
- (include_modeline_p ? window_modeline_height (w) : 0));
-
- default_face_height_and_width (window, &defheight, &defwidth);
-
- char_height = avail_height / defheight;
-
- /* It's the calling function's responsibility to check these values
- and make sure they're not out of range.
-
- #### We need to go through the calling functions and actually
- do this. */
- if (char_height < 0)
- return 0;
- else
- return char_height;
- }
-
- static int
- window_char_height_to_pixel_height (struct window *w, int char_height,
- int include_modeline_p)
- {
- int avail_height;
- int defheight, defwidth;
- int pixel_height;
-
- Lisp_Object window;
-
- XSETWINDOW (window, w);
-
- default_face_height_and_width (window, &defheight, &defwidth);
-
- avail_height = char_height * defheight;
- pixel_height = (avail_height +
- window_top_gutter_height (w) +
- window_bottom_gutter_height (w) -
- (include_modeline_p ? window_modeline_height (w) : 0));
-
-
- /* It's the calling function's responsibility to check these values
- and make sure they're not out of range.
-
- #### We need to go through the calling functions and actually
- do this. */
- if (pixel_height < 0)
- return 0;
- else
- return pixel_height;
- }
-
- /* Return number of default lines of text can fit in space not taken
- up by modeline and horizontal scrollbar (if INCLUDE_MODELINE_P is
- non-zero, however, include the modeline in the space considered).
- */
- int
- window_char_height (struct window *w, int include_modeline_p)
- {
- return window_pixel_height_to_char_height (w, WINDOW_HEIGHT (w),
- include_modeline_p);
- }
-
- /*
- * Return number of lines currently displayed in window w. If
- * end-of-buffer is displayed then the area below end-of-buffer is assume
- * to be blank lines of default height.
- * Does not include the modeline.
- */
- int
- window_displayed_height (struct window *w)
- {
- struct buffer *b = XBUFFER (w->buffer);
- display_line_dynarr *dla = window_display_lines (w, CURRENT_DISP);
- int num_lines;
- Charcount end_pos = (BUF_Z (b) - w->window_end_pos[CURRENT_DISP] > BUF_ZV (b)
- ? -1
- : w->window_end_pos[CURRENT_DISP]);
-
- if (!Dynarr_length (dla))
- return window_char_height (w, 0);
-
- num_lines = Dynarr_length (dla);
-
- /* #### Document and assert somewhere that w->window_end_pos == -1
- indicates that end-of-buffer is being displayed. */
- if (end_pos == -1)
- {
- struct display_line *dl = Dynarr_atp (dla, 0);
- int ypos1 = dl->ypos + dl->descent;
- int ypos2 = WINDOW_TEXT_BOTTOM (w);
- Lisp_Object window;
- int defheight, defwidth;
-
- XSETWINDOW (window, w);
-
- if (dl->modeline)
- {
- num_lines--;
-
- if (Dynarr_length (dla) == 1)
- ypos1 = WINDOW_TEXT_TOP (w);
- else
- {
- dl = Dynarr_atp (dla, Dynarr_length (dla) - 1);
- /* If this line is clipped then we know that there is no
- blank room between eob and the modeline. If we are
- scrolling on clipped lines just know off the clipped
- line and return .*/
- if (scroll_on_clipped_lines && dl->clip)
- return (num_lines - 1);
- ypos1 = dl->ypos + dl->descent - dl->clip;
- }
- }
-
- default_face_height_and_width (window, &defheight, &defwidth);
- /* #### This probably needs to know about the clipping area once a
- final definition is decided on. */
- num_lines += ((ypos2 - ypos1) / defheight);
- }
- else
- {
- if (num_lines > 1 && Dynarr_atp (dla, 0)->modeline)
- num_lines--;
-
- if (scroll_on_clipped_lines
- && Dynarr_atp (dla, Dynarr_length (dla) - 1)->clip)
- num_lines--;
- }
-
- return num_lines;
- }
-
- static int
- window_pixel_width (Lisp_Object window)
- {
- struct window *w = XWINDOW (window);
- return WINDOW_WIDTH (w);
- }
-
- static int
- window_pixel_width_to_char_width (struct window *w, int pixel_width,
- int include_margins_p)
- {
- int avail_width;
- int char_width;
- int defheight, defwidth;
- Lisp_Object window;
-
- XSETWINDOW (window, w);
-
- avail_width = (pixel_width -
- window_left_gutter_width (w, 0) -
- window_right_gutter_width (w, 0) -
- (include_margins_p ? 0 : window_left_margin_width (w)) -
- (include_margins_p ? 0 : window_right_margin_width (w)));
-
- default_face_height_and_width (window, &defheight, &defwidth);
-
- char_width = (avail_width / defwidth);
-
- /* It's the calling function's responsibility to check these values
- and make sure they're not out of range.
-
- #### We need to go through the calling functions and actually
- do this. */
- if (char_width < 0)
- return 0;
- else
- return char_width;
- }
-
- static int
- window_char_width_to_pixel_width (struct window *w, int char_width,
- int include_margins_p)
- {
- int avail_width;
- int pixel_width;
- int defheight, defwidth;
- Lisp_Object window;
-
- XSETWINDOW (window, w);
-
- default_face_height_and_width (window, &defheight, &defwidth);
-
- avail_width = char_width * defwidth;
- pixel_width = (avail_width +
- window_left_gutter_width (w, 0) +
- window_right_gutter_width (w, 0) +
- (include_margins_p ? 0 : window_left_margin_width (w)) +
- (include_margins_p ? 0 : window_right_margin_width (w)));
-
- /* It's the calling function's responsibility to check these values
- and make sure they're not out of range.
-
- #### We need to go through the calling functions and actually
- do this. */
- if (pixel_width < 0)
- return 0;
- else
- return pixel_width;
- }
-
- /* This returns the usable space which doesn't include space needed by
- scrollbars or divider lines. */
- int
- window_char_width (struct window *w, int include_margins_p)
- {
- return window_pixel_width_to_char_width (w, WINDOW_WIDTH (w),
- include_margins_p);
- }
-
- #define MINSIZE(w) \
- (widthflag \
- ? window_min_width * defwidth \
- : (defheight * (MINI_WINDOW_P (XWINDOW (w)) ? 1 : window_min_height)))
-
- #define CURBEG(w) \
- *(widthflag ? (int *) &WINDOW_LEFT (w) : (int *) &WINDOW_TOP (w))
-
- #define CURSIZE(w) \
- *(widthflag ? (int *) &WINDOW_WIDTH (w) : (int *) &WINDOW_HEIGHT (w))
-
- #define CURCHARSIZE(w) \
- (widthflag ? window_char_width (w, 0) : window_char_height (w, 1))
-
- #define MINCHARSIZE(window) \
- (widthflag ? window_min_width : MINI_WINDOW_P (XWINDOW (window)) \
- ? 1 : window_min_height)
-
- /* Unlike set_window_pixheight, this function
- also changes the heights of the siblings so as to
- keep everything consistent. */
-
- static void
- change_window_height (int delta, int widthflag)
- {
- Lisp_Object parent;
- Lisp_Object window;
- struct window *w;
- struct frame *f;
- int *sizep;
- int (*sizefun) (Lisp_Object) = (widthflag
- ? window_pixel_width
- : window_pixel_height);
- void (*setsizefun) (Lisp_Object, int, int) = (widthflag
- ? set_window_pixwidth
- : set_window_pixheight);
- int dim;
- int defheight, defwidth;
-
- if (delta == 0)
- return;
-
- check_min_window_sizes ();
-
- if (EQ (Fselected_window (Qnil),
- FRAME_ROOT_WINDOW
- (XFRAME (XWINDOW (Fselected_window (Qnil))->frame))))
- error ("Won't change only window");
-
- f = selected_frame ();
- window = Fselected_window (Qnil);
-
- /* #### This is very likely incorrect and instead the char_to_pixel_
- functions should be called. */
- default_face_height_and_width (window, &defheight, &defwidth);
-
- while (1)
- {
- w = XWINDOW (window);
- parent = w->parent;
- if (NILP (parent))
- {
- if (widthflag)
- error ("No other window to side of this one");
- break;
- }
- if (widthflag
- ? !NILP (XWINDOW (parent)->hchild)
- : !NILP (XWINDOW (parent)->vchild))
- break;
- window = parent;
- }
-
- sizep = &CURSIZE (w);
- dim = CURCHARSIZE (w);
-
- if ((dim + delta) < MINCHARSIZE (window))
- {
- if (MINI_WINDOW_P (XWINDOW (window)))
- return;
- else if (!NILP (parent))
- {
- Fdelete_window (window);
- return;
- }
- }
-
- delta *= (widthflag ? defwidth : defheight);
-
- {
- int maxdelta;
-
- maxdelta = ((!NILP (parent))
- ? (*sizefun) (parent) - *sizep
- : ((!NILP (w->next))
- ? (*sizefun) (w->next) - MINSIZE (w->next)
- : ((!NILP (w->prev))
- ? (*sizefun) (w->prev) - MINSIZE (w->prev)
- /* This is a frame with only one window,
- a minibuffer-only or a minibufferless frame. */
- : (delta = 0))));
-
- if (delta > maxdelta)
- /* This case traps trying to make the minibuffer
- the full frame, or make the only window aside from the
- minibuffer the full frame. */
- delta = maxdelta;
-
- if (delta == 0)
- return;
-
- #if 0 /* FSFmacs */
- /* #### Chuck: is this correct? */
- if (*sizep + delta < MINSIZE (window))
- {
- Fdelete_window (window);
- return;
- }
- #endif
- }
-
- if (!NILP (w->next) &&
- (*sizefun) (w->next) - delta >= (int) MINSIZE (w->next))
- {
- CURBEG (XWINDOW (w->next)) += delta;
- (*setsizefun) (w->next, (*sizefun) (w->next) - delta, 0);
- (*setsizefun) (window, *sizep + delta, 0);
- }
- else if (!NILP (w->prev) &&
- (*sizefun) (w->prev) - delta >= (int) MINSIZE (w->prev))
- {
- (*setsizefun) (w->prev, (*sizefun) (w->prev) - delta, 0);
- CURBEG (w) -= delta;
- (*setsizefun) (window, *sizep + delta, 0);
- }
- else
- {
- int delta1;
- int opht = (*sizefun) (parent);
-
- /* If trying to grow this window to or beyond size of the parent,
- make delta1 so big that, on shrinking back down,
- all the siblings end up with less than one line and are deleted. */
- if (opht <= *sizep + delta)
- delta1 = opht * opht * 2;
- /* Otherwise, make delta1 just right so that if we add delta1
- lines to this window and to the parent, and then shrink
- the parent back to its original size, the new proportional
- size of this window will increase by delta. */
- else
- delta1 = (delta * opht * 100) / ((opht - *sizep - delta) * 100);
-
- /* Add delta1 lines or columns to this window, and to the parent,
- keeping things consistent while not affecting siblings. */
- CURSIZE (XWINDOW (parent)) = opht + delta1;
- (*setsizefun) (window, *sizep + delta1, 0);
-
- /* Squeeze out delta1 lines or columns from our parent,
- shriking this window and siblings proportionately.
- This brings parent back to correct size.
- Delta1 was calculated so this makes this window the desired size,
- taking it all out of the siblings. */
- (*setsizefun) (parent, opht, 0);
- }
-
- SET_LAST_MODIFIED (w, 0);
- SET_LAST_FACECHANGE (w);
- MARK_FRAME_WINDOWS_STRUCTURE_CHANGED (f);
- }
- #undef MINSIZE
- #undef CURBEG
- #undef CURSIZE
- #undef CURCHARSIZE
- #undef MINCHARSIZE
-
-
-
- /* Scroll contents of window WINDOW up N lines. */
- void
- window_scroll (Lisp_Object window, Lisp_Object n, int direction, int no_error)
- {
- struct window *w = XWINDOW (window);
- struct buffer *b = XBUFFER (w->buffer);
- int selected = EQ (window, Fselected_window (Qnil));
- int value = 0;
- Bufpos opoint;
- Lisp_Object point, tem;
-
- if (selected)
- point = make_number (BUF_PT (b));
- else
- {
- Bufpos pos = marker_position (w->pointm[CURRENT_DISP]);
-
- if (pos < BUF_BEGV (b))
- pos = BUF_BEGV (b);
- else if (pos > BUF_ZV (b))
- pos = BUF_ZV (b);
-
- point = make_number (pos);
- }
-
- /* #### When the fuck does this happen? I'm so glad that history has
- completely documented the behavior of the scrolling functions under
- all circumstances. */
- tem = Fpos_visible_in_window_p (point, window);
- if (NILP (tem))
- {
- Fvertical_motion (make_number (-window_char_height (w, 0) / 2), window);
- Fset_marker (w->start[CURRENT_DISP], point, w->buffer);
- w->force_start = 1;
- opoint = BUF_PT (b);
- BUF_SET_PT (b, XINT (point));
- w->start_at_line_beg = !NILP (Fbolp (w->buffer));
- BUF_SET_PT (b, opoint);
- MARK_WINDOWS_CHANGED (w);
- }
-
- if (!NILP (n))
- {
- if (EQ (n, Qminus))
- direction *= -1;
- else
- {
- n = Fprefix_numeric_value (n);
- value = XINT (n) * direction;
-
- if (!value)
- return; /* someone just made a pointless call */
- }
- }
-
- /* If the user didn't specify how far to scroll then we have to figure it
- out by ourselves. */
- if (NILP (n) || EQ (n, Qminus))
- {
- /* Going forwards is easy. If that is what we are doing then just
- set value and the section which handles the user specifying a
- positive value will work. */
- if (direction == 1)
- {
- value = window_displayed_height (w) - next_screen_context_lines;
- value = (value < 1 ? 1 : value);
- }
-
- /* Going backwards is hard. We can't use the same loop used if the
- user specified a negative value because we care about
- next_screen_context_lines. In a variable height world you don't
- know how many lines above you can actually be displayed and still
- have the context lines appear. So we leave value set to 0 and add
- a separate section to deal with this. */
-
- }
-
- if (direction == 1 && !value)
- {
- return;
- }
- else if (value > 0)
- {
- int vtarget;
- Bufpos startp, old_start;
-
- old_start = marker_position (w->start[CURRENT_DISP]);
- startp = vmotion (w, old_start, value, &vtarget);
-
- if (vtarget < value &&
- (w->window_end_pos[CURRENT_DISP] == -1
- || (BUF_Z (b) - w->window_end_pos[CURRENT_DISP] > BUF_ZV (b))))
- {
- if (no_error)
- return;
- else
- signal_error (Qend_of_buffer, Qnil);
- }
- else
- {
- set_marker_restricted (w->start[CURRENT_DISP], make_number (startp),
- w->buffer);
- w->force_start = 1;
- opoint = BUF_PT (b);
- BUF_SET_PT (b, startp);
- w->start_at_line_beg = !NILP (Fbolp (w->buffer));
- BUF_SET_PT (b, opoint);
- MARK_WINDOWS_CHANGED (w);
-
- if (!point_would_be_visible (w, startp, XINT (point)))
- {
- if (selected)
- BUF_SET_PT (b, startp);
- else
- set_marker_restricted (w->pointm[CURRENT_DISP],
- make_number (startp),
- w->buffer);
- }
- }
- }
- else if (value < 0)
- {
- int vtarget;
- Bufpos startp, old_start;
-
- old_start = marker_position (w->start[CURRENT_DISP]);
- startp = vmotion (w, old_start, value, &vtarget);
-
- if (vtarget > value
- && marker_position (w->start[CURRENT_DISP]) == BUF_BEGV (b))
- {
- if (no_error)
- return;
- else
- signal_error (Qbeginning_of_buffer, Qnil);
- }
- else
- {
- set_marker_restricted (w->start[CURRENT_DISP], make_number (startp),
- w->buffer);
- w->force_start = 1;
- opoint = BUF_PT (b);
- BUF_SET_PT (b, startp);
- w->start_at_line_beg = !NILP (Fbolp (w->buffer));
- BUF_SET_PT (b, opoint);
- MARK_WINDOWS_CHANGED (w);
-
- if (!point_would_be_visible (w, startp, XINT (point)))
- {
- Bufpos new_point;
-
- if (MINI_WINDOW_P (w))
- new_point = startp;
- else
- new_point = start_of_last_line (w, startp);
-
- if (selected)
- BUF_SET_PT (b, new_point);
- else
- set_marker_restricted (w->pointm[CURRENT_DISP],
- make_number (new_point),
- w->buffer);
- }
- }
- }
- else /* value == 0 && direction == -1 */
- {
- if (marker_position (w->start[CURRENT_DISP]) == BUF_BEGV (b))
- {
- if (no_error)
- return;
- else
- signal_error (Qbeginning_of_buffer, Qnil);
- }
- else
- {
- int vtarget;
- int movement = next_screen_context_lines - 1;
- Bufpos old_startp = marker_position (w->start[CURRENT_DISP]);
- Bufpos bottom = vmotion (w, old_startp, movement, &vtarget);
- Bufpos startp =
- start_with_point_on_display_line (w, bottom,
- -1 - (movement - vtarget));
-
- if (startp >= old_startp)
- startp = vmotion (w, old_startp, -1, NULL);
-
- set_marker_restricted (w->start[CURRENT_DISP], make_number (startp),
- w->buffer);
- w->force_start = 1;
- opoint = BUF_PT (b);
- BUF_SET_PT (b, startp);
- w->start_at_line_beg = !NILP (Fbolp (w->buffer));
- BUF_SET_PT (b, opoint);
- MARK_WINDOWS_CHANGED (w);
-
- if (!point_would_be_visible (w, startp, XINT (point)))
- {
- Bufpos new_point = start_of_last_line (w, startp);
-
- if (selected)
- BUF_SET_PT (b, new_point);
- else
- set_marker_restricted (w->pointm[CURRENT_DISP],
- make_number (new_point),
- w->buffer);
- }
- }
- }
-
- }
-
- DEFUN ("scroll-up", Fscroll_up, Sscroll_up, 0, 1, "_P",
- "Scroll text of current window upward ARG lines; or near full screen if no ARG.\n\
- A near full screen is `next-screen-context-lines' less than a full screen.\n\
- Negative ARG means scroll downward.\n\
- When calling from a program, supply a number as argument or nil.")
- (n)
- Lisp_Object n;
- {
- window_scroll (Fselected_window (Qnil), n, 1, 0);
- return Qnil;
- }
-
- DEFUN ("scroll-down", Fscroll_down, Sscroll_down, 0, 1, "_P",
- "Scroll text of current window downward ARG lines; or near full screen if no ARG.\n\
- A near full screen is `next-screen-context-lines' less than a full screen.\n\
- Negative ARG means scroll upward.\n\
- When calling from a program, supply a number as argument or nil.")
- (n)
- Lisp_Object n;
- {
- window_scroll (Fselected_window (Qnil), n, -1, 0);
- return Qnil;
- }
-
- DEFUN ("other-window-for-scrolling", Fother_window_for_scrolling, Sother_window_for_scrolling, 0, 0, 0,
- "Return the other window for \"other window scroll\" commands.\n\
- If in the minibuffer, `minibuffer-scroll-window' if non-nil\n\
- specifies the window.\n\
- If `other-window-scroll-buffer' is non-nil, a window\n\
- showing that buffer is used.")
- ()
- {
- Lisp_Object window;
- Lisp_Object selected_window = Fselected_window (Qnil);
-
- if (MINI_WINDOW_P (XWINDOW (selected_window ))
- && !NILP (Vminibuf_scroll_window))
- window = Vminibuf_scroll_window;
- /* If buffer is specified, scroll that buffer. */
- else if (!NILP (Vother_window_scroll_buffer))
- {
- window = Fget_buffer_window (Vother_window_scroll_buffer, Qnil, Qnil);
- if (NILP (window))
- window = Fdisplay_buffer (Vother_window_scroll_buffer, Qt, Qnil);
- }
- else
- {
- /* Nothing specified; look for a neighboring window on the same
- frame. */
- window = Fnext_window (selected_window, Qnil, Qnil, Qnil);
-
- if (EQ (window, selected_window))
- /* That didn't get us anywhere; look for a window on another
- visible frame. */
- do
- window = Fnext_window (window, Qnil, Qt, Qnil);
- while (! FRAME_VISIBLE_P (XFRAME (WINDOW_FRAME (XWINDOW (window))))
- && ! EQ (window, selected_window));
- }
-
- CHECK_LIVE_WINDOW (window, 0);
-
- if (EQ (window, selected_window))
- error ("There is no other window");
-
- return window;
- }
-
- DEFUN ("scroll-other-window", Fscroll_other_window, Sscroll_other_window, 0, 1, "_P",
- "Scroll next window upward ARG lines; or near full frame if no ARG.\n\
- The next window is the one below the current one; or the one at the top\n\
- if the current one is at the bottom. Negative ARG means scroll downward.\n\
- When calling from a program, supply a number as argument or nil.\n\
- \n\
- If in the minibuffer, `minibuf-scroll-window' if non-nil\n\
- specifies the window to scroll.\n\
- If `other-window-scroll-buffer' is non-nil, scroll the window\n\
- showing that buffer, popping the buffer up if necessary.")
- (n)
- Lisp_Object n;
- {
- window_scroll (Fother_window_for_scrolling (), n, 1, 0);
- return Qnil;
- }
-
- DEFUN ("scroll-left", Fscroll_left, Sscroll_left, 0, 1, "_P",
- "Scroll selected window display ARG columns left.\n\
- Default for ARG is window width minus 2.")
- (arg)
- Lisp_Object arg;
- {
- Lisp_Object window = Fselected_window (Qnil);
- struct window *w = XWINDOW (window);
-
- if (NILP (arg))
- arg = make_number (window_char_width (w, 0) - 2);
- else
- arg = Fprefix_numeric_value (arg);
-
- return
- Fset_window_hscroll (window, make_number (w->hscroll + XINT (arg)));
- }
-
- DEFUN ("scroll-right", Fscroll_right, Sscroll_right, 0, 1, "_P",
- "Scroll selected window display ARG columns right.\n\
- Default for ARG is window width minus 2.")
- (arg)
- Lisp_Object arg;
- {
- Lisp_Object window = Fselected_window (Qnil);
- struct window *w = XWINDOW (window);
-
- if (NILP (arg))
- arg = make_number (window_char_width (w, 0) - 2);
- else
- arg = Fprefix_numeric_value (arg);
-
- return
- Fset_window_hscroll (window, make_number (w->hscroll - XINT (arg)));
- }
-
- DEFUN ("recenter", Frecenter, Srecenter, 0, 2, "_P",
- "Center point in WINDOW and redisplay frame. With ARG, put point on line ARG.\n\
- The desired position of point is always relative to the window.\n\
- Just C-u as prefix means put point in the center of the window.\n\
- No arg (i.e., it is nil) erases the entire frame and then\n\
- redraws with point in the center of the window.\n\
- If WINDOW is nil, the selected window is used.")
- (n, window)
- Lisp_Object n, window;
- {
- struct window *w;
- struct buffer *b;
- Bufpos startp;
- Bufpos opoint;
-
- if (NILP (window))
- window = Fselected_window (Qnil);
- else
- CHECK_WINDOW (window, 0);
- w = XWINDOW (window);
- b = XBUFFER (w->buffer);
-
- opoint = BUF_PT (b);
-
- if (NILP (n) || CONSP (n))
- {
- struct frame *f = XFRAME (w->frame);
-
- if (NILP (n))
- {
- MARK_FRAME_CHANGED (f);
- SET_FRAME_CLEAR (f);
- }
-
- startp = start_with_line_at_pixpos (w, opoint, window_half_pixpos (w));
- }
- else
- {
- n = Fprefix_numeric_value (n);
- CHECK_INT (n, 0);
-
- startp = start_with_point_on_display_line (w, opoint, XINT (n));
- }
-
- Fset_marker (w->start[CURRENT_DISP], make_number (startp), w->buffer);
- /* Is start_at_line_beg still needed? Do we still need to
- contort to set it? */
- BUF_SET_PT (b, startp);
- w->start_at_line_beg = !NILP (Fbolp (w->buffer));
- BUF_SET_PT (b, opoint);
-
- w->force_start = 1;
- MARK_WINDOWS_CHANGED (w);
- return Qnil;
- }
-
- DEFUN ("move-to-window-line", Fmove_to_window_line, Smove_to_window_line,
- 1, 2, "_P",
- "Position point relative to WINDOW.\n\
- With no argument, position text at center of window.\n\
- An argument specifies window line; zero means top of window,\n\
- negative means relative to bottom of window.\n\
- If WINDOW is nil, the selected window is used.")
- (arg, window)
- Lisp_Object arg, window;
- {
- struct window *w;
- struct buffer *b;
- int height;
- Bufpos start, new_point;
- int selected;
-
- if (NILP (window))
- window = Fselected_window (Qnil);
- else
- CHECK_WINDOW (window, 0);
- w = XWINDOW (window);
- b = XBUFFER (w->buffer);
-
- height = window_displayed_height (w);
- selected = EQ (window, Fselected_window (XFRAME (w->frame)->device));
-
- if (NILP (arg))
- {
- int retval;
-
- if (XINT (w->last_modified[CURRENT_DISP]) >= BUF_MODIFF (b)
- && XINT (w->last_facechange[CURRENT_DISP]) >= BUF_FACECHANGE (b))
- {
- new_point = point_at_center (w, CURRENT_DISP, 0, 0, 0);
-
- if (selected)
- BUF_SET_PT (b, new_point);
- else
- Fset_window_point (window, make_number (new_point));
-
- retval = line_at_center (w, CURRENT_DISP);
- }
- else
- {
- start = marker_position (w->start[CURRENT_DISP]);
- if (start < BUF_BEGV (b))
- start = BUF_BEGV (b);
- else if (start > BUF_ZV (b))
- start = BUF_ZV (b);
-
- if (selected)
- new_point = BUF_PT (b);
- else
- new_point = marker_position (w->pointm[CURRENT_DISP]);
-
- new_point = point_at_center (w, CMOTION_DISP, 1, start, BUF_PT (b));
-
- if (selected)
- BUF_SET_PT (b, new_point);
- else
- Fset_window_point (window, make_number (new_point));
-
- retval = line_at_center (w, CMOTION_DISP);
- }
-
- return (make_number (retval));
- }
- else
- {
- /* #### Is this going to work right when at eob? */
- arg = Fprefix_numeric_value (arg);
- if (XINT (arg) < 0)
- XSETINT (arg, XINT (arg) + height);
- }
-
- start = marker_position (w->start[CURRENT_DISP]);
- if (start < BUF_BEGV (b) || start > BUF_ZV (b))
- {
- if (selected)
- new_point = BUF_PT (b);
- else
- new_point = marker_position (w->pointm[CURRENT_DISP]);
-
- new_point = vmotion (XWINDOW (window), new_point, -height / 2, 0);
-
- if (selected)
- BUF_SET_PT (b, new_point);
- else
- Fset_window_point (window, make_number (new_point));
-
- Fset_marker (w->start[CURRENT_DISP], make_number (new_point),
- w->buffer);
- /* #### This isn't going to give the correct result if the
- window being worked with is not selected. */
- w->start_at_line_beg = !NILP (Fbolp (w->buffer));
- w->force_start = 1;
- }
- else
- {
- if (selected)
- BUF_SET_PT (b, start);
- else
- Fset_window_point (window, make_number (start));
- }
-
- if (selected)
- return Fvertical_motion (arg, window);
- else
- {
- int vpos;
- new_point = vmotion (XWINDOW (window),
- marker_position (w->pointm[CURRENT_DISP]),
- XINT (arg), &vpos);
- Fset_window_point (window, make_number (new_point));
- return make_number (vpos);
- }
- }
-
-
- static int
- map_windows_1 (Lisp_Object window,
- int (*mapfun) (struct window *w, void *closure),
- void *closure)
- {
- int retval;
-
- for (; !NILP (window); window = XWINDOW (window)->next)
- {
- struct window *w = XWINDOW (window);
- if (!NILP (w->vchild))
- retval = map_windows_1 (w->vchild, mapfun, closure);
- else if (!NILP (w->hchild))
- retval = map_windows_1 (w->hchild, mapfun, closure);
- else
- retval = (mapfun) (w, closure);
- if (retval)
- return retval;
- }
-
- return 0;
- }
-
- /* Map MAPFUN over the windows in F. CLOSURE is passed to each
- invocation of MAPFUN. If any invocation of MAPFUN returns non-zero,
- the mapping is halted and the value returned is the return value
- of map_windows(). Otherwise, map_windows() maps over all windows
- in F and returns 0. */
-
- int
- map_windows (struct frame *f, int (*mapfun) (struct window *w, void *closure),
- void *closure)
- {
- return map_windows_1 (FRAME_ROOT_WINDOW (f), mapfun, closure);
- }
-
-
- static void
- modeline_shadow_thickness_changed (Lisp_Object specifier, struct window *w,
- Lisp_Object oldval)
- {
- w->shadow_thickness_changed = 1;
- MARK_WINDOWS_CHANGED (w);
- }
-
- /* also used in scrollbar.c */
- void
- some_window_value_changed (Lisp_Object specifier, struct window *w,
- Lisp_Object oldval)
- {
- MARK_WINDOWS_CHANGED (w);
- }
-
-
- /************************************************************************/
- /* Window configurations */
- /************************************************************************/
-
- /* #### This window configuration stuff has had serious bugs lurking in it
- for years; it would be a -huge- win if this was reimplemented in lisp.
- */
-
- /* If you add anything to this structure make sure saved_window_equal
- knows about it. */
- struct saved_window
- {
- Lisp_Object window; /* window */
- Lisp_Object buffer; /* buffer */
- Lisp_Object start; /* copied marker */
- Lisp_Object pointm; /* copied marker */
- Lisp_Object sb_point; /* copied marker */
- Lisp_Object mark; /* copied marker */
- int pixel_left;
- int pixel_top;
- int pixel_width;
- int pixel_height;
- int hscroll;
- int parent_index; /* index into saved_windows */
- int prev_index; /* index into saved_windows */
- Lisp_Object dedicated;
- char start_at_line_beg; /* boolean */
- };
-
- /* If you add anything to this structure make sure window_config_equal
- knows about it. */
- struct window_config
- {
- struct lcrecord_header header;
- int frame_width;
- int frame_height;
- #if 0 /* FSFmacs */
- Lisp_Object selected_frame;
- #endif
- Lisp_Object current_window;
- Lisp_Object current_buffer;
- Lisp_Object minibuf_scroll_window;
- Lisp_Object root_window;
- #ifdef ENERGIZE
- /* The buffer whose p_sheets are visible */
- Lisp_Object p_sheet_buffer;
- #endif
- int saved_windows_count;
- /* Zero-sized arrays aren't ANSI C */
- struct saved_window saved_windows[1];
- };
- #define SAVED_WINDOW_N(conf, n) (&((conf)->saved_windows[(n)]))
-
- static Lisp_Object mark_window_config (Lisp_Object, void (*) (Lisp_Object));
- static void print_window_config (Lisp_Object, Lisp_Object, int);
- static unsigned int sizeof_window_config (CONST void *);
-
- DECLARE_LRECORD (window_configuration, struct window_config);
- #define XWINDOW_CONFIGURATION(x) XRECORD (x, window_configuration, struct window_config)
- #define XSETWINDOW_CONFIGURATION(x, p) XSETRECORD (x, p, window_configuration)
- #define WINDOW_CONFIGURATIONP(x) RECORDP (x, window_configuration)
- #define CHECK_WINDOW_CONFIGURATION(x, i) CHECK_RECORD (x, window_configuration)
-
- DEFINE_LRECORD_SEQUENCE_IMPLEMENTATION ("window-configuration",
- window_configuration,
- mark_window_config,
- print_window_config,
- 0, 0, 0, sizeof_window_config,
- struct window_config);
-
- static Lisp_Object
- mark_window_config (Lisp_Object obj, void (*markobj) (Lisp_Object))
- {
- struct window_config *config = XWINDOW_CONFIGURATION (obj);
- int i;
- ((markobj) (config->current_window));
- ((markobj) (config->current_buffer));
- ((markobj) (config->minibuf_scroll_window));
- ((markobj) (config->root_window));
- #ifdef ENERGIZE
- ((markobj) (config->p_sheet_buffer));
- #endif
- for (i = 0; i < config->saved_windows_count; i++)
- {
- struct saved_window *s = SAVED_WINDOW_N (config, i);
- ((markobj) (s->window));
- ((markobj) (s->buffer));
- ((markobj) (s->start));
- ((markobj) (s->pointm));
- ((markobj) (s->sb_point));
- ((markobj) (s->mark));
- ((markobj) (s->dedicated));
- }
- return (Qnil);
- }
-
- static unsigned int
- sizeof_window_config (CONST void *h)
- {
- CONST struct window_config *c = h;
- return (sizeof (*c)
- + ((c->saved_windows_count - 1) * sizeof (struct saved_window)));
- }
-
- static void
- print_window_config (Lisp_Object obj, Lisp_Object printcharfun, int escapeflag)
- {
- struct window_config *config = XWINDOW_CONFIGURATION (obj);
- char buf[200];
- if (print_readably)
- error ("printing unreadable object #<window-configuration 0x%x>",
- config->header.uid);
- write_c_string ("#<window-configuration ", printcharfun);
- sprintf (buf, "0x%x>", config->header.uid);
- write_c_string (buf, printcharfun);
- }
-
- /* Stolen from marker.c. The saved windows store copies of the
- markers so we can't just do an EQ test. */
- static int
- window_marker_equal (Lisp_Object o1, Lisp_Object o2)
- {
- if (EQ (o1, o2))
- return 1;
-
- if (!MARKERP (o1) || !MARKERP (o2))
- return 0;
-
- if (XMARKER (o1)->buffer != XMARKER (o2)->buffer)
- return 0;
- else if (!XMARKER (o1)->buffer)
- /* All markers pointing nowhere are equal */
- return 1;
- else
- return ((XMARKER (o1)->memind == XMARKER (o2)->memind));
- }
-
- /* Returns a boolean indicating whether the two saved windows are
- identical. */
- static int
- saved_window_equal (struct saved_window *win1, struct saved_window *win2)
- {
- if (!EQ (win1->window, win2->window))
- return 0;
- else if (!EQ (win1->buffer, win2->buffer))
- return 0;
- else if (!window_marker_equal (win1->start, win2->start))
- return 0;
- else if (!window_marker_equal (win1->pointm, win2->pointm))
- return 0;
- else if (!window_marker_equal (win1->sb_point, win2->sb_point))
- return 0;
- else if (!window_marker_equal (win1->mark, win2->mark))
- return 0;
- else if (win1->pixel_left != win2->pixel_left)
- return 0;
- else if (win1->pixel_top != win2->pixel_top)
- return 0;
- else if (win1->pixel_width != win2->pixel_width)
- return 0;
- else if (win1->pixel_height != win2->pixel_height)
- return 0;
- else if (win1->hscroll != win2->hscroll)
- return 0;
- else if (win1->parent_index != win2->parent_index)
- return 0;
- else if (win1->prev_index != win2->prev_index)
- return 0;
- else if (!EQ (win1->dedicated, win2->dedicated))
- return 0;
- else if (win1->start_at_line_beg != win2->start_at_line_beg)
- return 0;
-
- return 1;
- }
-
- /* Returns a boolean indicating whether the two given configurations
- are identical. */
- static int
- window_config_equal (Lisp_Object conf1, Lisp_Object conf2)
- {
- struct window_config *fig1, *fig2;
- int i;
-
- /* First check if they are truly the same. */
- if (EQ (conf1, conf2))
- return 1;
-
- fig1 = XWINDOW_CONFIGURATION (conf1);
- fig2 = XWINDOW_CONFIGURATION (conf2);
-
- if (fig1->saved_windows_count != fig2->saved_windows_count)
- return 0;
- else if (!EQ (fig1->current_window, fig2->current_window))
- return 0;
- else if (!EQ (fig1->current_buffer, fig2->current_buffer))
- return 0;
- else if (!EQ (fig1->root_window, fig2->root_window))
- return 0;
- else if (!EQ (fig1->minibuf_scroll_window, fig2->minibuf_scroll_window))
- return 0;
- else if (fig1->frame_width != fig2->frame_width)
- return 0;
- else if (fig1->frame_height != fig2->frame_height)
- return 0;
- #ifdef ENERGIZE
- else if (!EQ (fig1->p_sheet_buffer, fig2->p_sheet_buffer))
- return 0;
- #endif
-
- for (i = 0; i < fig1->saved_windows_count; i++)
- {
- if (!saved_window_equal (SAVED_WINDOW_N (fig1, i),
- SAVED_WINDOW_N (fig2, i)))
- return 0;
- }
-
- return 1;
- }
-
- DEFUN ("window-configuration-p", Fwindow_configuration_p,
- Swindow_configuration_p, 1, 1, 0,
- "T if OBJECT is a window-configuration object.")
- (obj)
- Lisp_Object obj;
- {
- return (WINDOW_CONFIGURATIONP (obj) ? Qt : Qnil);
- }
-
- /*
- * There are getting to be a lot of functions which traverse the
- * window structure doing various things. It may be worth writing a
- * generic map-windows function.
- * #### I just did. Feel free to rewrite. --ben
- */
- void
- mark_windows_in_use (Lisp_Object window, int mark)
- {
- for (; !NILP (window) ; window = XWINDOW (window)->next)
- {
- XWINDOW (window)->config_mark = mark;
-
- if (!NILP (XWINDOW (window)->vchild))
- mark_windows_in_use (XWINDOW (window)->vchild, mark);
- else if (!NILP (XWINDOW (window)->hchild))
- mark_windows_in_use (XWINDOW (window)->hchild, mark);
- }
- }
-
- DEFUN ("set-window-configuration",
- Fset_window_configuration, Sset_window_configuration,
- 1, 1, 0,
- "Set the configuration of windows and buffers as specified by CONFIGURATION.\n\
- CONFIGURATION must be a value previously returned\n\
- by `current-window-configuration' (which see).")
- (configuration)
- Lisp_Object configuration;
- {
- struct window *w;
- struct window_config *config;
- struct saved_window *p;
- Lisp_Object new_current_buffer;
- int k;
- Lisp_Object frame;
- struct frame *f;
- struct gcpro gcpro1;
- Lisp_Object old_window_config;
- int previous_frame_height;
- int previous_frame_width;
-
- GCPRO1 (configuration);
-
- CHECK_WINDOW_CONFIGURATION (configuration, 0);
- config = XWINDOW_CONFIGURATION (configuration);
-
- frame = XWINDOW (SAVED_WINDOW_N (config, 0)->window)->frame;
- f = XFRAME (frame);
-
- /* If the frame was deleted you can't restore the windows as they
- were deleted too. Raise an error. */
- if (!FRAME_LIVE_P (f))
- error ("Cannot set-window-configuration for a deleted frame");
-
- /* restore the frame characteristics */
- #ifdef ENERGIZE
- if (FRAME_IS_X (f))
- {
- Lisp_Object new_desired = config->p_sheet_buffer;
-
- if (BUFFERP (new_desired) &&
- !BUFFER_LIVE_P (XBUFFER (new_desired)))
- new_desired = Qnil; /* the desired buffer was killed */
-
- /* need to restore the desired buffer */
- if (!EQ (new_desired, desired_psheet_buffer (f)))
- make_psheets_desired (f, new_desired);
- }
- #endif
-
- new_current_buffer = config->current_buffer;
- if (!BUFFER_LIVE_P (XBUFFER (new_current_buffer)))
- new_current_buffer = Qnil;
-
- /*
- * Assumed precondition: w->config_mark = 0 for all w
- * This procedure should ensure this is true by the time it exits
- * to ensure the precondition for future calls.
- *
- * We use w->config_mark to know whether we're modifying a
- * window that is currently visible on the frame (#### we
- * should just be able to check whether the window is dead
- * or not, but this way is safer?). As we process each
- * window, we set its config_mark to 0. At the end, we
- * go through all the windows that used to be on the frame,
- * set each one's config_mark to 0 (to maintain the
- * assumed precondition) and delete each one that's no
- * longer in use.
- *
- * #### Using a window-configuration to keep track of
- * the current windows is wasteful. All we need is the
- * list of windows, so we could just use a dynarr.
- */
- old_window_config = Fcurrent_window_configuration (frame);
-
- /* If the new configuration is already equal to the old, then stop
- right here. This saves the work below and it also saves
- triggering a full redisplay of this window. This is a huge win
- when using the mouse since the mode motion code uses
- save-window-excursion extensively but will rarely cause the
- configuration to actually change. */
- if (window_config_equal (configuration, old_window_config))
- {
- UNGCPRO;
- return Qnil;
- }
-
- mark_windows_in_use (f->root_window, 1);
-
- previous_frame_width = FRAME_WIDTH (f);
- previous_frame_height = FRAME_HEIGHT (f);
- /* If the frame has been resized since this window configuration was
- made, we change the frame to the size specified in the
- configuration, restore the configuration, and then resize it
- back. We keep track of the prevailing height in these variables. */
- if (config->frame_height != FRAME_HEIGHT (f)
- || config->frame_width != FRAME_WIDTH (f))
- change_frame_size (f, config->frame_height, config->frame_width, 0, 0);
-
- /* OK, now restore all the windows in the window config.
- This may involve "undeleting" windows, since the
- windows in the window config may be deleted.
- */
- for (k = 0; k < config->saved_windows_count; k++)
- {
- p = SAVED_WINDOW_N (config, k);
- w = XWINDOW (p->window);
- w->next = Qnil;
-
- /* The window might be dead. In this case, its redisplay
- structures were freed, so we need to reallocate them. */
- if (!w->face_cache_elements)
- {
- w->face_cache_elements = Dynarr_new (struct face_cache_element);
- reset_face_cache_elements (w);
- }
- if (!w->glyph_cache_elements)
- w->glyph_cache_elements = Dynarr_new (struct glyph_cache_element);
- if (!w->line_start_cache)
- w->line_start_cache = Dynarr_new (struct line_start_cache);
- w->dead = 0;
-
- if (p->parent_index >= 0)
- w->parent = SAVED_WINDOW_N (config, p->parent_index)->window;
- else
- w->parent = Qnil;
-
- if (p->prev_index >= 0)
- {
- w->prev = SAVED_WINDOW_N (config, p->prev_index)->window;
-
- /* This is true for a minibuffer-only frame. */
- if (!NILP (w->mini_p) && EQ (w->prev, p->window))
- w->next = Qnil;
- else
- XWINDOW (w->prev)->next = p->window;
- }
- else
- {
- w->prev = Qnil;
- if (!NILP (w->parent))
- {
- if (WINDOW_WIDTH (p) == WINDOW_WIDTH (XWINDOW (w->parent)))
- {
- XWINDOW (w->parent)->vchild = p->window;
- XWINDOW (w->parent)->hchild = Qnil;
- }
- else
- {
- XWINDOW (w->parent)->hchild = p->window;
- XWINDOW (w->parent)->vchild = Qnil;
- }
- }
- }
- if (!w->config_mark)
- {
- /* #### This should be equivalent to the window previously
- having been dead. If we're brave, we'll put in an
- assertion to this effect. */
- MARK_FRAME_WINDOWS_STRUCTURE_CHANGED (f);
- }
- else /* if (!EQ (w->buffer, p->buffer)) */
- {
- /* With the new redisplay we let it know that a change has
- been made and it will take care of the rest. If we don't
- tell it something has possibly changed it could lead to
- incorrect display. */
- MARK_WINDOWS_CHANGED (w);
- }
-
- WINDOW_LEFT (w) = WINDOW_LEFT (p);
- WINDOW_TOP (w) = WINDOW_TOP (p);
- WINDOW_WIDTH (w) = WINDOW_WIDTH (p);
- WINDOW_HEIGHT (w) = WINDOW_HEIGHT (p);
- w->hscroll = p->hscroll;
- /* #### Here we need to restore the saved specs for
- has-modeline-p, scrollbar-width, scrollbar-height,
- modeline-shadow-thickness, left-margin-width,
- right-margin-width, and current-display-table. */
- w->dedicated = p->dedicated;
- w->line_cache_last_updated = Qzero;
- SET_LAST_MODIFIED (w, 1);
- SET_LAST_FACECHANGE (w);
- w->config_mark = 0;
-
- /* Reinstall the saved buffer and pointers into it. */
- if (NILP (p->buffer))
- w->buffer = p->buffer;
- else
- {
- if (BUFFER_LIVE_P (XBUFFER (p->buffer)))
- /* If saved buffer is alive, install it. */
- {
- w->buffer = p->buffer;
- w->start_at_line_beg = p->start_at_line_beg;
- set_marker_restricted (w->start[CURRENT_DISP],
- Fmarker_position (p->start),
- w->buffer);
- set_marker_restricted (w->pointm[CURRENT_DISP],
- Fmarker_position (p->pointm), w->buffer);
- set_marker_restricted (w->sb_point,
- Fmarker_position (p->sb_point),
- w->buffer);
- Fset_marker (XBUFFER (w->buffer)->mark,
- Fmarker_position (p->mark), w->buffer);
-
- /* As documented in Fcurrent_window_configuration, don't
- save the location of point in the buffer which was current
- when the window configuration was recorded. */
- if (!EQ (p->buffer, new_current_buffer) &&
- XBUFFER (p->buffer) == current_buffer)
- Fgoto_char (w->pointm[CURRENT_DISP], Fcurrent_buffer ());
- }
- else if (NILP (w->buffer) || !BUFFER_LIVE_P (XBUFFER (w->buffer)))
- /* Else if window's old buffer is dead too, get a live one. */
- {
- /* #### The following line makes me nervous... */
- /* w->buffer = Fcdr (Fcar (XFRAME (w->frame)->buffer_alist));*/
- w->buffer = Fget_buffer_create (QSscratch);
- /* w->buffer = Fother_buffer (Qnil, w->frame, Qnil); */
- /* This will set the markers to beginning of visible range. */
- set_marker_restricted (w->start[CURRENT_DISP], Qzero, w->buffer);
- set_marker_restricted (w->pointm[CURRENT_DISP], Qzero,
- w->buffer);
- set_marker_restricted (w->sb_point, Qzero, w->buffer);
- w->start_at_line_beg = 1;
- }
- else
- /* Keeping window's old buffer; make sure the markers are real. */
- {
- /* Set window markers at start of visible range. */
- if (XMARKER (w->start[CURRENT_DISP])->buffer == 0)
- set_marker_restricted (w->start[CURRENT_DISP], Qzero,
- w->buffer);
- if (XMARKER (w->sb_point)->buffer == 0)
- set_marker_restricted (w->sb_point, Qzero, w->buffer);
- if (XMARKER (w->pointm[CURRENT_DISP])->buffer == 0)
- set_marker_restricted (w->pointm[CURRENT_DISP],
- make_number
- (BUF_PT (XBUFFER (w->buffer))),
- w->buffer);
- w->start_at_line_beg = 1;
- }
- /* We just potentially changed the window's buffer and
- potentially turned a dead window into a live one,
- so we need to recompute the cached specifier values. */
- recompute_all_cached_specifiers_in_window (w);
- }
- }
-
- FRAME_ROOT_WINDOW (f) = config->root_window;
-
- #if 0 /* FSFmacs */
- if (NILP (config->focus_frame)
- || (FRAMEP (config->focus_frame)
- && FRAME_LIVE_P (XFRAME (config->focus_frame))))
- Fredirect_frame_focus (frame, config->focus_frame);
- #endif
-
- /* Set the frame height to the value it had before this function. */
- if (previous_frame_height != FRAME_HEIGHT (f)
- || previous_frame_width != FRAME_WIDTH (f))
- change_frame_size (f, previous_frame_height, previous_frame_width,
- 0, 0);
-
- /* If restoring in the current frame make the window current, otherwise
- just update the frame selected_window slot to be the restored
- current_window. */
- if (f == selected_frame ())
- {
- Fselect_window (config->current_window);
- if (!NILP (new_current_buffer))
- Fset_buffer (new_current_buffer);
- else
- Fset_buffer (XWINDOW (Fselected_window (Qnil))->buffer);
- #ifdef ENERGIZE
- energize_buffer_shown_hook (XWINDOW (Fselected_window (Qnil)));
- #endif
- }
- else
- f->selected_window = config->current_window;
-
- #if 0 /* FSFmacs */
- /* Fselect_window will have made f the selected frame, so we
- reselect the proper frame here. Fhandle_switch_frame will change the
- selected window too, but that doesn't make the call to
- Fselect_window above totally superfluous; it still sets f's
- selected window. */
- if (FRAME_LIVE_P (XFRAME (config->selected_frame)))
- Fhandle_switch_frame (config->selected_frame, Qnil);
- #endif
-
- Vminibuf_scroll_window = config->minibuf_scroll_window;
-
- config = XWINDOW_CONFIGURATION (old_window_config);
- for (k = 0; k < config->saved_windows_count; k++)
- {
- p = SAVED_WINDOW_N (config, k);
- w = XWINDOW (p->window);
- /* Remember, we set w->config_mark on all currently visible
- windows, and reset it on all newly visible windows.
- Any windows still marked need to be deleted. */
- if (w->config_mark)
- {
- mark_window_as_deleted (w);
- w->config_mark = 0;
- }
- }
-
- UNGCPRO;
-
- f->mirror_dirty = 1;
-
- return (Qnil);
- }
-
- /* Mark all subwindows of a window as deleted. The argument
- W is actually the subwindow tree of the window in question. */
-
- void
- delete_all_subwindows (struct window *w)
- {
- if (!NILP (w->next))
- delete_all_subwindows (XWINDOW (w->next));
- if (!NILP (w->vchild))
- delete_all_subwindows (XWINDOW (w->vchild));
- if (!NILP (w->hchild))
- delete_all_subwindows (XWINDOW (w->hchild));
-
- mark_window_as_deleted (w);
- }
-
-
- static int
- count_windows (struct window *window)
- {
- int count = 1;
- if (!NILP (window->next))
- count += count_windows (XWINDOW (window->next));
- if (!NILP (window->vchild))
- count += count_windows (XWINDOW (window->vchild));
- if (!NILP (window->hchild))
- count += count_windows (XWINDOW (window->hchild));
- return count;
- }
-
- static int
- saved_window_index (Lisp_Object window, struct window_config *config, int lim)
- {
- int j;
- for (j = 0; j < lim; j++)
- {
- if (EQ (SAVED_WINDOW_N (config, j)->window, window))
- {
- return (j);
- }
- }
- abort ();
- return 0; /* suppress compiler warning */
- }
-
- static int
- save_window_save (Lisp_Object window, struct window_config *config, int i)
- {
- struct saved_window *p;
- struct window *w;
-
- for (; !NILP (window); window = w->next)
- {
- p = SAVED_WINDOW_N (config, i);
- w = XWINDOW (window);
-
- i++;
- p->window = window;
- p->buffer = w->buffer;
- WINDOW_LEFT (p) = WINDOW_LEFT (w);
- WINDOW_TOP (p) = WINDOW_TOP (w);
- WINDOW_WIDTH (p) = WINDOW_WIDTH (w);
- WINDOW_HEIGHT (p) = WINDOW_HEIGHT (w);
- p->hscroll = w->hscroll;
- /* #### Here we need to save the specs for
- has-modeline-p, scrollbar-width, scrollbar-height,
- modeline-shadow-thickness, left-margin-width,
- right-margin-width, and current-display-table. */
- if (!NILP (w->buffer))
- {
- /* Save w's value of point in the window configuration.
- If w is the selected window, then get the value of point
- from the buffer; pointm is garbage in the selected window. */
- if (EQ (window, Fselected_window (Qnil)))
- {
- p->pointm = Fmake_marker ();
- Fset_marker (p->pointm,
- make_number (BUF_PT (XBUFFER (w->buffer))),
- w->buffer);
- }
- else
- p->pointm = Fcopy_marker (w->pointm[CURRENT_DISP]);
-
- p->start = Fcopy_marker (w->start[CURRENT_DISP]);
- p->sb_point = Fcopy_marker (w->sb_point);
- p->start_at_line_beg = w->start_at_line_beg;
-
- p->mark = Fcopy_marker (XBUFFER (w->buffer)->mark);
- }
- else
- {
- p->pointm = Qnil;
- p->start = Qnil;
- p->sb_point = Qnil;
- p->mark = Qnil;
- p->start_at_line_beg = 0;
- }
-
- if (NILP (w->parent))
- p->parent_index = -1;
- else
- p->parent_index = saved_window_index (w->parent, config, i);
- if (NILP (w->prev))
- p->prev_index = -1;
- else
- p->prev_index = saved_window_index (w->prev, config, i);
- p->dedicated = w->dedicated;
- if (!NILP (w->vchild))
- i = save_window_save (w->vchild, config, i);
- if (!NILP (w->hchild))
- i = save_window_save (w->hchild, config, i);
- }
-
- return i;
- }
-
- #if 0 /* FSFmacs */
- /* Added to doc string:
-
- This also records the currently selected frame, and FRAME's focus\n\
- redirection (see `redirect-frame-focus').
-
- */
- #endif
-
- DEFUN ("current-window-configuration",
- Fcurrent_window_configuration, Scurrent_window_configuration, 0, 1, 0,
- "Return an object representing the current window configuration of FRAME.\n\
- If FRAME is nil or omitted, use the selected frame.\n\
- This describes the number of windows, their sizes and current buffers,\n\
- and for each displayed buffer, where display starts, and the positions of\n\
- point and mark. An exception is made for point in the current buffer:\n\
- its value is -not- saved.")
- (frame)
- Lisp_Object frame;
- {
- Lisp_Object result = Qnil;
- struct frame *f;
- int n_windows;
-
- struct window_config *config;
-
- f = get_frame (frame);
-
- n_windows = count_windows (XWINDOW (FRAME_ROOT_WINDOW (f)));
- config = alloc_lcrecord ((int) ((sizeof (struct window_config)
- /* n_windows - 1 because zero-sized arrays
- * aren't ANSI C */
- + ((n_windows - 1)
- * sizeof (struct saved_window)))),
- lrecord_window_configuration);
- XSETWINDOW_CONFIGURATION (result, config);
-
- config->frame_width = FRAME_WIDTH (f);
- config->frame_height = FRAME_HEIGHT (f);
- config->current_window = FRAME_SELECTED_WINDOW (f);
- XSETBUFFER (config->current_buffer, current_buffer);
- config->minibuf_scroll_window = Vminibuf_scroll_window;
- config->root_window = FRAME_ROOT_WINDOW (f);
- config->saved_windows_count = n_windows;
- #ifdef ENERGIZE
- {
- config->p_sheet_buffer = desired_psheet_buffer (f);
- if (EQ (config->p_sheet_buffer, Qzero)) /* #### necessaryp? */
- config->p_sheet_buffer = Qnil;
- }
- #endif
- save_window_save (FRAME_ROOT_WINDOW (f), config, 0);
- return (result);
- }
-
- DEFUN ("save-window-excursion", Fsave_window_excursion, Ssave_window_excursion,
- 0, UNEVALLED, 0,
- "Execute body, preserving window sizes and contents.\n\
- Restores which buffer appears in which window, where display starts,\n\
- as well as the current buffer.\n\
- Does not restore the value of point in current buffer.")
- (args)
- Lisp_Object args;
- {
- /* This function can GC */
- Lisp_Object val;
- int speccount = specpdl_depth ();
-
- record_unwind_protect (Fset_window_configuration,
- Fcurrent_window_configuration (Qnil));
- val = Fprogn (args);
- return unbind_to (speccount, val);
- }
-
-
- /************************************************************************/
- /* initialization */
- /************************************************************************/
-
- void
- syms_of_window (void)
- {
- defsymbol (&Qwindowp, "windowp");
- defsymbol (&Qwindow_live_p, "window-live-p");
- defsymbol (&Qwindow_configurationp, "window-configuration-p");
- defsymbol (&Qscroll_up, "scroll-up");
- defsymbol (&Qscroll_down, "scroll-down");
- defsymbol (&Qvisible, "visible");
-
- defsubr (&Sselected_window);
- defsubr (&Sminibuffer_window);
- defsubr (&Swindow_minibuffer_p);
- defsubr (&Swindowp);
- defsubr (&Swindow_live_p);
- defsubr (&Swindow_lowest_p);
- defsubr (&Swindow_highest_p);
- defsubr (&Spos_visible_in_window_p);
- defsubr (&Swindow_buffer);
- defsubr (&Swindow_frame);
- defsubr (&Swindow_height);
- defsubr (&Swindow_width);
- defsubr (&Swindow_pixel_height);
- defsubr (&Swindow_pixel_width);
- defsubr (&Swindow_hscroll);
- defsubr (&Sset_window_hscroll);
- defsubr (&Swindow_pixel_edges);
- defsubr (&Swindow_point);
- defsubr (&Swindow_start);
- defsubr (&Swindow_end);
- defsubr (&Sset_window_point);
- defsubr (&Sset_window_start);
- defsubr (&Swindow_dedicated_p);
- defsubr (&Sset_window_buffer_dedicated);
- defsubr (&Snext_window);
- defsubr (&Sprevious_window);
- defsubr (&Snext_vertical_window);
- defsubr (&Sother_window);
- defsubr (&Sget_lru_window);
- defsubr (&Sget_largest_window);
- defsubr (&Sget_buffer_window);
- defsubr (&Swindow_left_margin_pixel_width);
- defsubr (&Swindow_right_margin_pixel_width);
- defsubr (&Sdelete_other_windows);
- defsubr (&Sdelete_windows_on);
- defsubr (&Sreplace_buffer_in_windows);
- defsubr (&Sdelete_window);
- defsubr (&Sset_window_buffer);
- defsubr (&Sselect_window);
- defsubr (&Sdisplay_buffer);
- defsubr (&Ssplit_window);
- defsubr (&Senlarge_window);
- defsubr (&Sshrink_window);
- defsubr (&Sscroll_up);
- defsubr (&Sscroll_down);
- defsubr (&Sscroll_left);
- defsubr (&Sscroll_right);
- defsubr (&Sother_window_for_scrolling);
- defsubr (&Sscroll_other_window);
- defsubr (&Srecenter);
- defsubr (&Smove_to_window_line);
- defsubr (&Swindow_configuration_p);
- defsubr (&Sset_window_configuration);
- defsubr (&Scurrent_window_configuration);
- defsubr (&Ssave_window_excursion);
- }
-
- void
- vars_of_window (void)
- {
- /* Make sure all windows get marked */
- minibuf_window = Qnil;
- staticpro (&minibuf_window);
-
- DEFVAR_BOOL ("scroll-on-clipped-lines", &scroll_on_clipped_lines,
- "*Non-nil means to scroll if point lands on a line which is clipped.");
- scroll_on_clipped_lines = 1;
-
- DEFVAR_LISP ("temp-buffer-show-function", &Vtemp_buffer_show_function,
- "Non-nil means call as function to display a help buffer.\n\
- Used by `with-output-to-temp-buffer'.");
- Vtemp_buffer_show_function = Qnil;
-
- DEFVAR_LISP ("display-buffer-function", &Vdisplay_buffer_function,
- "If non-nil, function to call to handle `display-buffer'.\n\
- It will receive three args: the same as those to `display-buffer'.");
- Vdisplay_buffer_function = Qnil;
-
- DEFVAR_LISP ("pre-display-buffer-function", &Vpre_display_buffer_function,
- "If non-nil, function that will be called from `display-buffer'\n\
- as the first action. It will receive three args: the same as those\n\
- to `display-buffer'.\n\
- This function may be used to select an appropriate frame for the buffer,\n\
- for example. See also the variable `display-buffer-function', which may\n\
- be used to completely replace the `display-buffer' function.");
- Vpre_display_buffer_function = Qnil;
-
- DEFVAR_LISP ("minibuffer-scroll-window", &Vminibuf_scroll_window,
- "Non-nil means it is the window that \\<minibuffer-local-map>\\[scroll-other-window] in minibuffer should scroll.");
- Vminibuf_scroll_window = Qnil;
-
- DEFVAR_LISP ("other-window-scroll-buffer", &Vother_window_scroll_buffer,
- "If non-nil, this is a buffer and \\[scroll-other-window] should scroll its window.");
- Vother_window_scroll_buffer = Qnil;
-
- #if 0 /* FSFmacs */
- xxDEFVAR_BOOL ("pop-up-frames", &pop_up_frames,
- "*Non-nil means `display-buffer' should make a separate frame.");
- pop_up_frames = 0;
-
- xxDEFVAR_LISP ("pop-up-frame-function", &Vpop_up_frame_function,
- "Function to call to handle automatic new frame creation.\n\
- It is called with no arguments and should return a newly created frame.\n\
- \n\
- A typical value might be `(lambda () (new-frame pop-up-frame-alist))'\n\
- where `pop-up-frame-alist' would hold the default frame parameters.");
- Vpop_up_frame_function = Qnil;
-
- xxDEFVAR_LISP ("special-display-buffer-names", &Vspecial_display_buffer_names,
- "*List of buffer names that should have their own special frames.\n\
- Displaying a buffer whose name is in this list makes a special frame for it\n\
- using `special-display-function'. See also `special-display-regexps'.");
- Vspecial_display_buffer_names = Qnil;
-
- xxDEFVAR_LISP ("special-display-regexps", &Vspecial_display_regexps,
- "*List of regexps saying which buffers should have their own special frames.\n\
- If a buffer name matches one of these regexps, it gets its own frame.\n\
- Displaying a buffer whose name is in this list makes a special frame for it\n\
- using `special-display-function'. See also `special-display-buffer-names'.");
- Vspecial_display_regexps = Qnil;
-
- xxDEFVAR_LISP ("special-display-function", &Vspecial_display_function,
- "Function to call to make a new frame for a special buffer.\n\
- It is called with one argument, the buffer,\n\
- and should return a window displaying that buffer.\n\
- The default value makes a separate frame for the buffer,\n\
- using `special-display-alist' to specify the frame parameters.\n\
- \n\
- A buffer is special if its is listed in `special-display-buffer-names'\n\
- or matches a regexp in `special-display-regexps'.");
- Vspecial_display_function = Qnil;
- #endif
-
- DEFVAR_BOOL ("pop-up-windows", &pop_up_windows,
- "*Non-nil means display-buffer should make new windows.");
- pop_up_windows = 1;
-
- DEFVAR_INT ("next-screen-context-lines", &next_screen_context_lines,
- "*Number of lines of continuity when scrolling by screenfuls.");
- next_screen_context_lines = 2;
-
- DEFVAR_INT ("split-height-threshold", &split_height_threshold,
- "*display-buffer would prefer to split the largest window if this large.\n\
- If there is only one window, it is split regardless of this value.");
- split_height_threshold = 500;
-
- DEFVAR_INT ("split-width-threshold", &split_width_threshold,
- "*display-buffer would prefer to split the largest window if this large.\n\
- If there is only one window, it is split regardless of this value.");
- split_width_threshold = 500;
-
- DEFVAR_INT ("window-min-height", &window_min_height,
- "*Delete any window less than this tall (including its modeline).");
- window_min_height = 4;
-
- DEFVAR_INT ("window-min-width", &window_min_width,
- "*Delete any window less than this wide.");
- window_min_width = 10;
- }
-
- void
- specifier_vars_of_window (void)
- {
- DEFVAR_SPECIFIER ("modeline-shadow-thickness", &Vmodeline_shadow_thickness,
- "*How thick to draw 3D shadows around modelines.\n\
- If this is set to 0, modelines will be the traditional 2D. Sizes above\n\
- 10 will be accepted but the maximum thickness that will be drawn is 10.\n\
- This is a specifier; use `set-specifier' to change it.");
- Vmodeline_shadow_thickness = Fmake_specifier (Qinteger);
- /* The initial value for modeline-shadow-thickness is 2, but if the
- user removes all specifications we provide a fallback value of 0,
- which is probably what was expected. */
- set_specifier_fallback (Vmodeline_shadow_thickness,
- list1 (Fcons (Qnil, Qzero)));
- Fadd_spec_to_specifier (Vmodeline_shadow_thickness, make_number (2),
- Qnil, Qnil, Qnil);
- set_specifier_caching (Vmodeline_shadow_thickness,
- slot_offset (struct window,
- modeline_shadow_thickness),
- modeline_shadow_thickness_changed,
- 0, 0);
-
- DEFVAR_SPECIFIER ("has-modeline-p", &Vhas_modeline_p,
- "*Whether the modeline should be displayed.\n\
- This is a specifier; use `set-specifier' to change it.");
- Vhas_modeline_p = Fmake_specifier (Qboolean);
- set_specifier_fallback (Vhas_modeline_p,
- list1 (Fcons (Qnil, Qt)));
- set_specifier_caching (Vhas_modeline_p,
- slot_offset (struct window,
- has_modeline_p),
- /* #### It's strange that we need a special
- flag to indicate that the shadow-thickness
- has changed, but not one to indicate that
- the modeline has been turned off or on. */
- some_window_value_changed,
- 0, 0);
- }
-